我在eval()
方法中使用initialize
:
class ActiveRecord::FakedModel
def initialize(attributes={})
attributes = {} if not attributes
attributes.each do |attr_name, value|
eval("@#{attr_name}=#{value.inspect}")
end
@attributes = attributes
end
...
end
并有一个用于清理空格的setter:
class ContactForm < ActiveRecord::FakedModel
attr_accessor :plz
def plz=(plz)
@plz = plz.try(:delete,' ')
end
...
end
但是当我在散列中给出'plz'时,这个setter不起作用:
c=ContactForm.new(:plz=>' 1 3 3 3 ')
=> #<ContactForm:0x1024e3a10 @attributes={:plz=>" 1 3 3 3 "}, @plz=" 1 3 3 3 ">
在eval
中使用setter有什么问题吗?
答案 0 :(得分:3)
您的eval语句未调用setter方法,它直接设置实例变量。如果您希望构造函数使用setter,请使用send:
attributes.each do |attr_name, value|
send "#{attr_name}=", value
end
答案 1 :(得分:2)
使用Object#instance_variable_set方法设置实例变量。
attributes.each do |attr_name, value|
self.instance_variable_set("@#{attr_name}", value.inspect)
end
答案 2 :(得分:1)
要动态执行方法,请使用Object#send
。
class ActiveRecord::FakedModel
def initialize(attributes={})
attributes = {} if not attributes
attributes.each do |attr_name, value|
send("#{attr_name}=", value)
end
@attributes = attributes
end
end
您还可以获得不需要调用inspect并强制转换为变量String的优势。
您也可以使用Object#instance_variable_set
,但在这种情况下,您绕过了setter方法,如果您在setter中有一些自定义逻辑,例如强制转换,则代码将无法正常工作。
class ActiveRecord::FakedModel
def initialize(attributes={})
attributes = {} if not attributes
attributes.each do |attr_name, value|
instance_variable_set("@#{attr_name}", value)
end
@attributes = attributes
end
end