当属性更改时更新 Ruby 类属性哈希
我正在尝试编写一个 Ruby 类,其工作方式类似于 Rails AactiveRecord 模型,其处理属性的方式如下:
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
我的意思是,当我初始化该类时,“属性”哈希会使用相关属性进行更新:
>>> p = Person.new(:name => 'John', :age => 30)
>>> p.attributes
=> {:age=>30, :name=>"John"}
>>> p.attributes = { :name => 'charles' }
>>> p.attributes
=> {:age=>30, :name=>"charles"}
到目前为止好的。我想要发生的是在设置单个属性时更新属性哈希:
>>> 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"}
我可以通过为每个属性编写 setter 和 getter 而不是使用 attr_accessor 来做到这一点,但这会很糟糕一个有很多字段的模型。有什么快速方法可以实现这一点吗?
I'm trying to write a Ruby class that works similarly to Rails AactiveRecord 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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题是您将属性保存为单独的 ivars,并保存在
@attributes
哈希中。您应该只选择和使用一种方法。如果你想使用散列,你应该以自己的方式创建访问器,这会将它们“重新路由”到一个可以设置和从散列获取的方法:
如果你想使用 ivars,你应该再次滚动您自己的 attr_accessor 方法还会记住哪些 ivars 应该是“属性”,并在 attribute 方法中使用该列表。
attributes
方法会动态创建它们的哈希值,然后返回它。在这里您可以找到一篇关于实现访问器的好文章。
The problem is that you keep your attributes both as separate ivars, and within a
@attributes
hash. You should choose and use only one way.If you want to use a hash, you should make your own way of creating accessors, which would "reroute" them to a single method which would set and get from a hash:
If you want to use ivars, you should, again, roll your own
attr_accessor
method which would, in addition, remember which ivars should be "attributes", and use that list inattributes
method. Andattributes
method would create a hash out of them on-the-fly, and return it.Here you can find a nice article about implementing accessors.