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

时间:2013-01-09 12:08:24

标签: ruby-on-rails validation attributes instance-variables local-variables

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

我希望在下面的自定义验证中使用@title代替title,但下面的代码中@titleniltitle包含实际数据。

    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

2 个答案:

答案 0 :(得分:3)

如果从验证或其他实例方法访问这些,这并不重要。你可以从控制台看到发生了什么(撬):

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)。

答案 1 :(得分:1)

ActiveRecord将值存储在attributes哈希中,而不是实例变量中。当你访问它时,我会动态生成访问器(getter / setter)方法。

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

接下来是关联,它们是通过代理处理的,所以你需要用方法调用它们。

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