A few months ago I created a custom class to enhance the base Ruby Struct object. What I needed for my Whois library was the ability to create a new instance from a Hash.
Loser = Struct.new(:id, :name)
Winner = SuperStruct.new(:id, :name)
# The default Struct accepts up to N arguments
# where N is the total number of elements defined in the Struct.
Loser.new(:id => "1", :name => "John Doe")
# => #<struct Loser id={:name=>"John Doe", :id=>"1"}, name=nil>
Winner.new(:id => "1", :name => "John Doe")
# => #<struct Winner id="1", name="John Doe">
Because the first argument is mapped to the :id element, the Hash is stored as value for the id attribute.
In a standard Ruby Struct I have to map each Hash value to the specific position in the Struct, loosing the flexibility of passing a Hash with optional keys.
hash = { :name => "John Doe" }
Loser.new(hash)
# => #<struct Loser id={:name=>"John Doe"}, name=nil>
Loser.new(nil, hash[:name])
# => #<struct Loser id=nil, name="John Doe">
Winner.new(hash)
# => #<struct Winner id=nil, name="John Doe">
Also, I’d like to be able to pass a block to the initialize method and yield on self.
Loser.new do |c| c.name = "John Doe" end # => #<struct Loser id=nil, name=nil> # Name is not set Winner.new do |c| c.name = "John Doe" end # => #<struct Winner id=nil, name="John Doe"> # Hurra! Name is set!
I called it RubyStruct. It was created for the Ruby Whois, but ultimately I found myself using it quite often in my projects and I decided to package it in a single file along with a basic test suite.
Here’s the library.
A minor point, but in your example code it should be Winner and Loser, not Winner and Looser!
It was nice to have the same number of chars for both variable names! :D
I believe it’s the second time I mistype the same word… I should fix my internal spell checker!
Thanks John.
Not to worry, it’s a very common mistake and you should see my Italian! ;-)