我在工作中遇到了这个奇怪的问题所以我创建了一个最小的应用程序来突出问题。我有两个简单关联的模型:
class Parent < ActiveRecord::Base
has_many :children
end
和
class Child < ActiveRecord::Base
belongs_to :parent
named_scope :only_adults, :conditions => "adult is true"
end
现在我做的时候
p = Parent.first
p.children.only_adults.all()
我希望rails生成一个包含所有条件的SQL查询。但是,这就是我在日志中看到的内容:
Child Load (0.5ms) SELECT * FROM "children" WHERE ("children".parent_id = 1)
Child Load (0.3ms) SELECT * FROM "children" WHERE ("children".parent_id = 1) AND ((adult is true) AND ("children".parent_id = 1))
第一个查询基本上是无用的,并且在大型集合的情况下可以非常耗时。
有没有人知道为什么rails会这样做?
请注意,而不是做
p.children.only_adults.all()
我做
Child.by_parent(p.id).only_adults.all()
其中by_parent
是命名范围,然后我只得到一个查询。
还要注意parent_id条件的重复。这不是什么大问题。
感谢您的反馈。
答案 0 :(得分:3)
原因与Rails 2.3.x中执行查询的方式有关,而不是Rails 3.0.x.在Rails 2中,无论您附加到查询的其余部分的命名范围如何,调用p.children都将自动执行查询。解决这个问题的唯一方法是组合使用named_scopes,就像在“Child.by_parent(p.id).only_adults.all()”中一样,因为命名范围保留了推迟查询的行为。在Rails 3中,查询建立直到找到execute关键字(count,all,first,last),因此可以在单个查询中执行以下操作:
class Child < ActiveRecord::Base
belongs_to :parent
scope :only_adults, where(adult: true)
end
Parent.first.children.only_adults.all()
# SELECT * FROM "children" WHERE ("children".parent_id = 1) AND (adult is true)