我正在努力将旧版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关系中的作用感到好奇。任何人都可以向我解释这里究竟出了什么问题?
答案 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代码的地方。
如何找到这个:
def []
:执行grep -r 'def \[\]' ./activerecord/
class Base
:执行grep -r 'class Base' ./activerecord/
def []
个搜索结果与class base
中包含的模块进行比较(类本身定义在activerecord/lib/active_record/base.rb
文件底部附近。