3

カスタム検証メソッドで、属性がインスタンス変数としてアクセス可能ではなく、ローカル変数として渡されるのはなぜですか?

以下のカスタム検証の@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ですか?

4

2 に答える 2

3

検証または他のインスタンス メソッドからこれらにアクセスするかどうかは問題ではありません。コンソールから何が起こっているかを確認できます (pry):

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

于 2013-01-09T12:53:10.480 に答える
1

ActiveRecord は値をattributesインスタンス変数ではなくハッシュに格納します。アクセサー (getter/setter) メソッドは、アクセス中にその場で生成されます。

Rails はエンティティのライブサイクルをサポートする必要があり、このコードを生成されたメソッドにラップします。これは、つまりをサポートできるようにするために必要です。dirty?およびchanged?方法。

次はアソシエーションです。これらはプロキシを介して処理されるため、メソッドでも呼び出す必要があります。

インスタンス変数は、揮発性データと見なされる可能性があります。それらは永続層に対して透過的です。

于 2013-01-09T12:49:00.183 に答える