Roll your own OpenStruct

OpenStruct is a class from the Ruby Standard Library. Here’s how it’s described in the docs:

OpenStruct is a data structure, similar to a Hash, that allows the definition of arbitrary attributes with their accompanying values.
Basically, it uses metaprogramming and the method_missing method to obtain some really cool functionality that allows you to dynamically set attributes and store values. Take a look at the example they provide:

require 'ostruct'

person = OpenStruct.new

person.name    = "John Smith"
person.age     = 70
person.pension = 300

puts person.name     # -> "John Smith"
puts person.age      # -> 70
puts person.address  # -> nil

When I first saw this, I decided I wanted to try to roll my own version using method missing and an Hash to maintain the Struct’s state. The end result is this:

class MyOpenStruct
  def initialize
    @attrs = {}
  end

  def method_missing(method_name, *args)
    attribute = method_name.to_s
    if attribute =~ /=$/
      @attrs[attribute.chop] = args[0]
    else
      @attrs[attribute]
    end
  end
end

me = MyOpenStruct.new
me.first_name = "Kevin"
me.last_name  = "Curtin"
me.rubyist    = true

me.first_name #=> Kevin
me.last_name #=> Curtin
me.rubyist #=> true

me.inspect #=> #<MyOpenStruct:0x007f9b890864d0 @attrs={"first_name"=>"Kevin", "last_name"=>"Curtin", "rubyist"=>true}>

Whenever a method that isn’t defined is called on an MyOpenStruct instance, the method_missing method is called. The name of the method is passed in along with the value if there was one. If the method called was a setter method (i.e. anything=) I define the method name as the key in a hash and point it to the value that was sent in. If the method is not a setter method, I just return that value from the hash.