Ruby Method for Casting - ruby

I am new to ruby development and I am making a simple chat server encrypted over TLS.
I have managed to get the basic server running however I now want to add special properties to each of the connected clients (username, etc.)
I have this class which I plan to use for each client that connects:
class Client < OpenSSL::SSL::SSLSocket
attr_accessor :username
...
end
I need to get a Client object from the OpenSSL::SSL::SSLServer.accept function in order to set the username attribute. I am used to C type languages where casting would do the trick but Google has told me that this is not the case in Ruby.
What is the Ruby way of doing this?

You don't need casting in Ruby. It's a dynamic language. So what matters is if the object knows how to respond to a message (method).

There are essentially 2 ways to solve your problem:
delegation: create Client as a wrapper with an instance variable of class OpenSSL::SSL::SSLSocket. Client would then have to understand and forward messages to SSLSocket. Could get complicated.
extension: use class_eval to add instance variables and/or methods directly to SSLSocket. This is a commonly-used Ruby approach.

Related

Ruby Data Structures #?

how do I extract #hostname value out of this data? e.g. to do what I was expecting puts output[:hostname]
{:status=>"passed",
:code_desc=>"Host example.com port 80 proto tcp is expected to be reachable",
:run_time=>0.207583,
:start_time=>"2020-08-27T21:02:07+01:00",
:resource_title=>
#<#<Class:0x00007f87f71ebeb0>:0x00007f87f71eaf38
#__backend_runner__=
Inspec::Backend::Class #transport=Train::Transports::Local::Connection,
#__resource_name__=:host,
#host_provider=
#<Inspec::Resources::DarwinHostProvider:0x00007f87f71e9a20
#has_nc=true,
#has_ncat=true,
#has_net_redirections=true,
#inspec=
Inspec::Backend::Class #transport=Train::Transports::Local::Connection>,
#hostname="example.com",
#ip_cache=["93.184.216.34", "2606:2800:220:1:248:1893:25c8:1946"],
#ping_cache=
{:success=>true,
:connection=>"Connection to example.com port 80 [tcp/http] succeeded!\n",
:socket=>""},
#port=80,
#protocol="tcp",
#resource_exception_message=nil,
#resource_failed=false,
#resource_skipped=false,
#supports=[{:platform=>"unix"}, {:platform=>"windows"}]>,
:expectation_message=>"is expected to be reachable",
:waiver_data=>nil}
Any help on documentation would be very gratefully received.
If there's no accessor method Kaom Te writes about here https://stackoverflow.com/a/63623855/299774, then use instance_variable_get like this:
output[:resource_title].instance_variable_get(:#hostname)
But! Be careful! The fact that someone didn't provide this accessor as a public method means they wanted to encapsulate this data.
So, if you're doing it for some production system - it can surprise you to learn after next gem update that #hostname is no longer there (name was changed), or (even worse) it's still there but contains different data. It's an internal implementation detail that might be subject for change.
On the other hand, if this object comes from an open-source project - make a PR and make it part of a public interface.
Assuming the code sample you provided is meant to be a hash, and that the hash is assigned to the variable output, then there are possibly two ways of doing this but each has issues.
First, let's make clear that you're attempting to read output[:resource_title], which is an object of some class that has an instance variable #hostname that holds the value example.com, and that you want some way to read that hostname value.
output[:resource_title] is an instance of some class. Instances can have instance variables and in this case it has the instance variable #hostname. It's possible to read instance variables directly in Ruby but generally this is discouraged because if the author wanted users to be able to read that value then the author would have added a getter method to allow that value to be read.
We can't tell if there is a getter method there or not, so the easiest way to check is just to try accessing the method:
output[:resource_title].hostname
If this raises an error like NoMethodError: undefined method 'hostname' then there is no getter method and you need to read the instance variable directly. Even though it's discouraged, Ruby is flexible enough to make it pretty easy to do:
output[:resource_title].instance_variable_get('#hostname')
=> "example.com"
Assuming that data is in the variable output and there is a hostname accessor method on the object under the key :resource_title, then the code would be:
output[:resource_title].hostname

Store a class instance in session server side w/ Padrino?

I have a class that reads from a DB on startup. I'd prefer to be able to store it in the session, but I get the following error when trying to do so:
ERROR TypeError: no marshal_dump is defined for class Mutex
Is what I'm doing possible/reasonable? If so how should I go about doing it? If not, whats a good alternative to storing the class instance in the session? Currently my workaround is just instantiating it whenever I need to use it, but that doesn't strike me as a good solution or one that will be able to scale.
A good alternative is to store the id of the record in the session. Then when you need that data again you'd use a helper to return the data either from memory or from the database. A perfect example is the pattern used in current_user helper methods found in many ruby authentication gems. You could modify this helper to use a cache layer if you find it to be a bottleneck, but I'd leave that as an optimization after the fact.
Issues of having to get the object into a marshaled format that will live happily in a session, there are issues with storage space, stale data and possibly unintentional exposure to confidential data.

How does rails determine the path from an object?

I have been working on implementing my own ORM. And I was wondering how the rails path helper extracts the ID from the object. For example how would I make this work for my ORM?
#contact = Contact.first
contact_path(#contact)
Any help would be greatly appreciated!
Update:
My object does have an ID attribute and responds to it. But yet the path helper returns an error.
In a nutshell you want to be activemodel compliant. This will make url helpers, form_for(#contact) and so on work.
You also get to (optionally) use a bunch of modules dealing with
things such as validations, dirty attributes etc.
There are only a handful of methods you have to implement. There's also an
ActiveModel::Lint module that tests that your implementations of these
primitives are valid, and which also serves as documentation. In particular you need to implement to_param and persisted?. I think some of the naming stuff only gets used if you do stuff like link_to 'foo', #contact
The method checks to see if you've passed it an object, or an integer. If it's an object and that object has an id method (respond_to?(:id)), it uses its ID. Pretty dead simple.

What separates a Ruby DSL from an ordinary API

What are some defining characteristics of a Ruby DSL that separate it from just a regular API?
When you use an API you instantiate objects and call methods in an imperative manner. On the other hand a good DSL should be declarative, representing rules and relationships in your problem domain, not instructions to be executed. Moreover ideally DSL should be readable and modifiable by somebody who is not a programmer (which is not the case with APIs).
Also please keep in mind the distinction between internal and external DSLs.
Internal domain specific language is embedded in a programming language (eg. Ruby). It's easy to implement, but the structure of the DSL is dependent on the parent language it is embedded in.
External domain specific language is a separate language designed with the particular domain in mind. It gives you a greater flexibility when it comes to syntax, but you have to implement the code to interpret it. It's also more secure, as the person editing domain rules doesn't have access to all the power of the parent language.
DSL (domain specific language) is an over-hyped term. If you are simply using a sub-set of a language (say Ruby), how is it a different language than the original? The answer is, it isn't.
However, if you do some preprocessing of the source text to introduce new syntax or new semantics not found in the core language then you indeed have a new language, which may be domain-specific.
The combination of Ruby's poetry mode and operator overloading does present the possibility of having something that is at the same time legal Ruby syntax and a reasonable DSL.
And the continued aggravation that is XML does show that perhaps the simple DSL built into all those config files wasn't completely misguided..
Creating a DSL:
Adding new methods to the Object class so that you can just call them as if they were built-in language constructs. (see rake)
Creating methods on a custom object or set of objects, and then having script files run the statements in the context of a top-level object. (see capistrano)
API design:
Creating methods on a custom object or set of objects, so the user creates an object to use the methods.
Creating methods as class methods, so that the user prefixes the classname in front of all the methods.
Creating methods as a mixin that users include or extend to use the methods in their custom objects.
So yes, the line is thin between them. It's trivial to turn a custom set of objects into a DSL by adding one method that runs a script file in the right context.
The difference between a DSL and an API to me is that a DSL could be at least understood (and verified) if not written as a sub-language of Ruby by someone in that domain.
For example, you could have financial analysts writing rules for a stock trading application in a Ruby DSL and they would never have to know they were using Ruby.
They are, in fact, the same thing. DSLs are generally implemented via the normal language mechanisms in Ruby, so technically they're all APIs.
However, for people to recognize something as a DSL, it usually ends up adding what look like declarative statements to existing classes. Something like the validators and relationship declarations in ActiveRecord.
class Foo << ActiveRecord::Base
validates_uniqueness_of :name
validates_numericality_of :number, :integer_only => true
end
looks like a DSL, while the following doesn't:
class Foo <<ActiveRecord::BAse
def validate
unless unique? name
errors.add(:name, "must be unique")
end
unless number.to_s.match?(/^[-]?\d$/)
errors.add(:number, "must be an integer")
end
end
end
They're both going to be implemented by normal Ruby code. It's just that one looks like you've got cool new language constructs, while the other seems rather pedestrian (and overly verbose, etc. etc.)

OO Design: Multiple persistance design for a ruby class

I am designing a class for log entries of my mail server. I have parsed the log entries and created the class hierarchy. Now I need to save the in memory representation to the disk. I need to save it to multiple destinations like mysql and disk files. I am at a loss to find out the proper way to design the persistence mechanism. The challenges are:
How to pass persistence
initialization information like
filename, db connection parameters
passed to them. The options I can
think of are all ugly for eg:
1.1 Constructor: it becomes ugly as I
add more persistence.
1.2 Method: Object.mysql_params(" "),
again butt ugly
"Correct" method name to call each
persistance mechanism: eg:
Object.save_mysql, Object.save_file,
or Object.save (mysql) and
Object.save(file)
I am sure there is some pattern to solve this particular problem. I am using ruby as my language, with out any rails, ie pure ruby code. Any clue is much welcome.
raj
Personally I'd break things out a bit - the object representing a log entry really shouldn't be worrying about how it should save it, so I'd probably create a MySQLObjectStore, and FileObjectStore, which you can configure separately, and gets passed the object to save. You could give your Object class a class variable which contains the store type, to be called on save.
class Object
cattr_accessor :store
def save
##store.save(self)
end
end
class MySQLObjectStore
def initialize(connection_string)
# Connect to DB etc...
end
def save(obj)
# Write to database
end
end
store = MySQLObjectStore.new("user:password#localhost/database")
Object.store = store
obj = Object.new(foo)
obj.save
Unless I completely misunstood your question, I would recommend using the Strategy pattern. Instead of having this one class try to write to all of those different sources, delegate that responsibility to another class. Have a bunch of LogWriter classes, each one with the responsibility of persiting the object to a particular data store. So you might have a MySqlLogWriter, FileLogWriter, etc.
Each one of these objects can be instantiated on their own and then the persitence object can be passed to it:
lw = FileLogWriter.new "log_file.txt"
lw.Write(log)
You really should separate your concerns here. The message and the way the message is saved are two separate things. In fact, in many cases, it would also be more efficient not to open a new mysql connection or new file pointer for every message.
I would create a Saver class, extended by FileSaver and MysqlSaver, each of which have a save method, which is passed your message. The saver is responsible for pulling out the parts of the message that apply and saving them to the medium it's responsible for.

Resources