Generate accessors for an hash

Hello, I need to generate read and write accessors for all the keys in
an hash.
Say I have an attribute named my_attribute, I need "my_attribute" and
"my_attribute=" methods to read and write it to
@attributes[my_attribute].

I tried this code in the class constructor:

    for a in all_attributes
      method_name = a.name
      self.class.class_eval do
        define_method method_name do
          @attributes[method_name]
        end
        define_method method_name+"=" do |val|
          @attributes[method_name] = val
        end
      end
    end

It generates the method for the class, but all the methods read and
write to the last attribute in the all_attributes list. That's
strange...
Thank you,

Andrea Gianarro

···

--
Posted via http://www.ruby-forum.com/.

I tried this code in the class constructor:

   for a in all_attributes
     method_name = a.name
     self.class.class_eval do
       define_method method_name do
         @attributes[method_name]
       end
       define_method method_name+"=" do |val|
         @attributes[method_name] = val
       end
     end
   end

It generates the method for the class, but all the methods read and
write to the last attribute in the all_attributes list. That's
strange...

Ah, the strange joy that is closures. Basically, those 'define_method' calls
allow the code block to retain access to whatever variables were in scope
when the methods are defined. So, when those methods actually run, the
variable 'method_name' will have the last value in the loop -- each closure
references a single variable, it does not copy its value.

You might be better off with method_missing

class Hash
  def method_missing(name, value = nil)
    name = name.to_s
    if name =~ /=$/
      self[name.sub(/=$/, '')] = value
    else
      return self[name]
    end
  end
end

Andrea Gianarro wrote:

Hello, I need to generate read and write accessors for all the keys in
an hash.

Wouldn't a simpler solution be to use OpenStruct?

require 'ostruct'

hash={"my_attribute"=>"value"}
s=OpenStruct.new(hash)
puts s.my_attribute
> value
s.my_attribute="new"
=> "new"
puts s.my_attribute
> new
=> nil

And you get the freebie of creating new keys from the setter:

s.new_attribute="better"
=> "better"
puts s.new_attribute
> better

Cheers,
V.-

···

--
http://www.braveworld.net/riva

James Coglan wrote:

You might be better off with method_missing

class Hash
  def method_missing(name, value = nil)
    name = name.to_s
    if name =~ /=$/
      self[name.sub(/=$/, '')] = value
    else
      return self[name]
    end
  end
end

Thank you very much, that's exactly what I did. Strange ruby behaviour
anyway. :stuck_out_tongue:
bye,

Andrea Gianarro

···

--
Posted via http://www.ruby-forum.com/\.