属性作为局部变量与Rails验证中的实例变量



在自定义验证方法中,为什么属性作为局部变量传递,而不是作为实例变量访问?

我希望在下面的自定义验证中使用@title而不是title,但@title在下面的代码中是niltitle包含实际数据

    attr_accessible :title
    validate :do_check_title
    def do_check_title
      title =~ /^Alice in/ || errors.add(:title, "Not Alice in Wonderland")
    end

查看active_record/core.rb

   def initialize(attributes = nil)
     ...
     assign_attributes(attributes) if attributes
     ...
   end

然后在active_record/attribute_assignment。rb

   def _assign_attribute(k, v)
     public_send("#{k}=", v)

所以我猜,属性应该在验证函数中作为实例变量可用。

为什么是nil ?

从验证方法或其他实例方法访问这些都无关紧要。你可以从控制台看到发生了什么:

u = User.first
show-method u.first_name=

结果是这样的:

generated_attribute_methods.module_eval("def #{attr_name}=(new_value); write_attribute('#{attr_name}', new_value); end", __FILE__, __LINE__)

现在如果你看一下write_attribute方法,你可以看到它删除属性缓存等,然后分配给attributes,它只是一个哈希。

u.attributes

所以从现在开始,你可以用这个代替无聊的u.first_name = "foo":

u.send :write_attribute, "first_name", "foo"

,它会做同样的事情(3.2.10)。

ActiveRecord将值存储在attributes散列中,而不是在实例变量中。当您访问访问器(getter/setter)方法时,它会动态地生成这些方法。

Rails需要支持实体的生命周期,并将此代码封装在生成的方法中。这是必需的,这样它才能支持ie。dirty?changed?方法。

下一件事是关联,它们是通过代理处理的,所以你也需要用方法调用它们。

实例变量可以被视为易失性数据。它们对持久层是透明的。

最新更新