Yann Klis wrote:
In fact, I'd like to mimic the behaviour of ActiveRecord.
If I have something like this:
class Base
def initialize(attributes)
#do something clever with attributes
end
end
class MyObject < Base
end
I'd like to be able to do that:
object = MyObject.new({"attribute1" => "value1", "attribute2" =>
"value2"})
val = object.attribute1
To create methods on the class itself so all instances of that class get the method you can do:
class A
def initialize( args=nil )
if args.is_a? Hash
args.each { |key,val| self.class.send( :define_method, key, proc { val } ) }
end
end
end
a = A.new( :zzz => "testing" )
puts a.zzz
b = A.new
puts b.zzz
To create methods on the instance you have created only you can do:
class A
def initialize( args=nil )
if args.is_a? Hash
s = class << self; self; end
args.each { |key,val| s.send( :define_method, key, proc { val } ) }
end
end
end
a = A.new( :zzz => "testing" )
puts a.zzz
b = A.new
puts b.zzz #this will throw an error,because method zzz doesn't exist on this instance
Note, that I think the second example above is bad design. We are relying on an instance of A to give the class A extra methods for all instances. We should instead rely on a singleton method for class A to handle this task. (keep reading)
The above two solutions don't take into consideration if a method already exists though, so you could easily overwrite an existing method. Another way to do this is by overriding the method missing for your class which won't override existing methods. The below will handle things for instances only, like the first example:
class A
def initialize( args={} )
@args = args if args.is_a? Hash
end
def method_missing( method )
@args[method] || super
end
end
puts A.new( :a => "z" ) # prints out "z"
A.new.a #throws an error because :a wasn't passed in to this object
And you can alter that to add methods for the class also so all instances get the methods, although above in the second example I think we used bad designed. So here we fix it by using a singleton method 'add_attributes':
class A
def self.add_attributes( attributes )
@@attributes = attributes
end
def initialize( args={} )
@args = args if args.is_a? Hash
end
def method_missing( method )
@@attributes[method] || super
end
end
A.add_attributes( :attr1 => "attribute 1", :attr2 => "attribute 2" )
puts A.new.attr1
puts A.new.attr2
I hope this helps!
Zach