1

私はレガシーRailsアプリを3.0から3.2にアップグレードする作業をしていて、ActiveRecordからの本当に不可解な振る舞いに遭遇しました。私は2つの非常に単純なモデルを持っています:

class Newsletter < ActiveRecord::Base
  has_many :newsletter_entries

  def [](key)
    # Weird old code, not related to NewsletterEntry
  end

  # etc.
end

class NewsletterEntry < ActiveRecord::Base
  belongs_to :newsletter

  # etc.
end

Rails 3.0ブランチでは、これはすべて正常に機能します。しかし、私のRails 3.2ブランチでは、何らかの理由で、ニュースレターでnewsletter_entriesを呼び出すと常に空に戻ります。SQLステートメントを調べると、処理しているニュースレターの実際の主キーに関係なく、ActiveRecordが常にnewsletter_entriesテーブルでnewsletter_id=NULLのエントリを検索していることがすぐにわかりました。このコンソール出力の最後にあるSQLについて考えてみます。

> newsletter = Newsletter.create! :title => "Proof of Concept"
### SQL and irrelevant fields omitted
=> #<Newsletter id: 13, title: "Proof of Concept", created_at: "2013-02-28 00:44:25", updated_at: "2013-02-28 00:44:25"> 

> newsletter.newsletter_entries
  NewsletterEntry Load (0.4ms)  SELECT `newsletter_entries`.* FROM `newsletter_entries` WHERE `newsletter_entries`.`newsletter_id` IS NULL
=> [] 

何度も泣き叫んだり歯を食いしばったりした後、私は問題をニュースレターモデルのカスタム[]メソッドにまでさかのぼりました。それを削除すると、すべてが正常に戻ります。そのオーバーライドは、そもそもコードの臭いでした。ソースがわかったので、問題を簡単に解決できます。しかし、全体的な問題により、ActiveRecordの関係における[]の役割について病的に興味をそそられました。誰かが私にここで正確に何が悪かったのか説明できますか?

4

1 に答える 1

1

クラスは、で定義されているNewsletterから継承します。ActiveRecord::Baseactiverecord/lib/active_record/base.rb

内部に含まれるモジュールの1つclass BaseAttributeMethods、で定義されてactiverecord/lib/active_record/attribute_methods.rbいるです。

そして、定義されたメソッドがあります:

# activerecord/lib/active_record/attribute_methods.rb
def [](attr_name)
  read_attribute(attr_name) { |n| missing_attribute(n, caller) }
end

ここで、コードがRailsコードを壊します。

これを見つける方法:

  • Railsリポジトリのクローン。
  • すべて検索def []:実行grep -r 'def \[\]' ./activerecord/
  • 検索class Base:実行grep -r 'class Base' ./activerecord/
  • このクラスを開き、すべての検索結果を(ファイルの下部近くに定義されたクラス自体)def []に含まれるモジュールと比較します。class baseactiverecord/lib/active_record/base.rb
于 2013-03-05T07:12:54.577 に答える