0

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

并有一个用于清理空格的设置器:

class ContactForm < ActiveRecord::FakedModel
  attr_accessor :plz

  def plz=(plz)
    @plz = plz.try(:delete,' ')
  end
...
end

但是当我在哈希中给出“plz”时,这个设置器不起作用:

c=ContactForm.new(:plz=>' 1  3 3 3 ')
=> #<ContactForm:0x1024e3a10 @attributes={:plz=>" 1  3 3 3 "}, @plz=" 1  3 3 3 ">

在中使用设置器有什么问题eval吗?

4

3 回答 3

3

您的 eval 语句没有调用 setter 方法,而是直接设置实例变量。如果您希望构造函数使用 setter,请使用send

attributes.each do |attr_name, value|
  send "#{attr_name}=", value
end
于 2012-06-15T10:08:07.173 回答
2

使用 Object#instance_variable_set方法设置实例变量。

attributes.each do |attr_name, value|
  self.instance_variable_set("@#{attr_name}", value.inspect)
end
于 2012-06-15T10:06:44.583 回答
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

您还可以获得不需要调用检查并强制转换为变量字符串的优势。

您也可以使用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
于 2012-06-15T10:10:40.880 回答