Rails 3.2 - 为什么覆盖[]混淆了很多关系?

时间:2013-02-28 01:55:06

标签: ruby-on-rails-3 activerecord has-many

我正在努力将旧版Rails应用程序从3.0升级到3.2,并且从ActiveRecord遇到了一些非常令人困惑的行为。我有两个非常简单的模型:

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
=> [] 

经过大量的嚎叫和咬牙切齿之后,我将问题追溯到Newsletter模型上的custom []方法 - 删除它,一切都恢复正常。这个覆盖是一个代码气味开始,我现在可以很容易地解决问题,因为我知道源 - 但整个事件让我对[]在ActiveRecord关系中的作用感到好奇。任何人都可以向我解释这里究竟出了什么问题?

1 个答案:

答案 0 :(得分:1)

您的Newsletter类继承自ActiveRecord::Base中定义的activerecord/lib/active_record/base.rb

class Base中包含的模块之一是AttributeMethods,其在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代码的地方。

如何找到这个:

  • Clone Rails存储库。
  • 查找所有def []:执行grep -r 'def \[\]' ./activerecord/
  • 查找class Base:执行grep -r 'class Base' ./activerecord/
  • 打开此课程,将所有def []个搜索结果与class base中包含的模块进行比较(类本身定义在activerecord/lib/active_record/base.rb文件底部附近。