Yann said:
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