Hi,
I'm trying to write a ruby class that works similarly to rails activerecord model in the way that attributes are handled:
class Person
attr_accessor :name, :age
# init with Person.new(:name => 'John', :age => 30)
def initialize(attributes={})
attributes.each { |key, val| send("#{key}=", val) if respond_to?("#{key}=") }
@attributes = attributes
end
# read attributes
def attributes
@attributes
end
# update attributes
def attributes=(attributes)
attributes.each do |key, val|
if respond_to?("#{key}=")
send("#{key}=", val)
@attributes[key] = name
end
end
end
end
What I mean is that when I init the class, an "attributes" hash is updated with the relevant attributes:
>>> p = Person.new(:name => 'John', :age => 30)
>>> p.attributes
=> {:age=>30, :name=>"John"}
>>> p.attributes = { :name => 'charles' }
>>> p.attributes
=> {:age=>30, :name=>"charles"}
So far so good. What I want to happen is for the attributes hash to update when I set an individual property:
>>> p.attributes
=> {:age=>30, :name=>"John"}
>>> p.name
=> "John"
>>> p.name = 'charles' # <--- update an individual property
=> "charles"
>>> p.attributes
=> {:age=>30, :name=>"John"} # <--- should be {:age=>30, :name=>"charles"}
I could do that by writing a setter and getter for every attribute instead of using attr_accessor
, but that'll suck for a model that has a lot of fields. Any quick way to accomplish this? thanks
EDIT: Added solution
class Person
my_attr_accessor :name, :age, :attributes
# init with Person.new(:name => 'John', :age => 30)
def initialize(attributes={})
@attributes = {}
attributes.each { |key, val| send("#{key}=", val) if respond_to?("#{key}=") }
end
# read attributes
def attributes
@attributes
end
# update attributes
def attributes=(options)
options.each { |key, val| send("#{key}=", val) if respond_to?("#{key}=") }
end
end
class Class
def my_attr_accessor(*accessors)
accessors.each do |m|
define_method(m) { @attributes[m] }
define_method("#{m}=") { |val| @attributes[m]=val }
end
end
end