Rails 3拒绝急于加载
我在Rails 3.0.7中工作。
我有一些多对多和一些一对多的关联,无法加载。
我的协会是:
Person has_many :friends Person has_many :locations through=> :location_histories Location belongs_to :location_hour Location_hour has_many :locations
在我的控制器中,我有以下内容:
@people = Person.includes([[:locations=>:location_hour],:friends]).where("(location_histories.current = true) AND (people.name LIKE ? OR friends.first_name LIKE ? OR friends.last_name LIKE ? OR (friends.first_name LIKE ? AND friends.last_name LIKE ?))").limit(10).all
然后在我看来,我有:
locations.current是一个定义为:
scope :current, lambda { where("location_histories.current = ?", true) }
这按预期工作,首先生成2个数据库调用:一个用于获取人员ID列表,然后是一个大型数据库调用,其中所有内容都已正确连接。 问题是,之后有以下几行数据库调用:
SELECT 'friends'.* from 'friends' WHERE ('friends'.person_id = 12345)
因此,对于视图中循环的每次迭代。 不用说这需要一段时间。
我想是的。所有人都会急切加载。 任何人都知道这里发生了什么?
这在ActiveRecord上花费超过3秒。 太久了。
我非常感谢任何和所有的建议。
谢谢。
好。 终于解决了。
我需要调用两个连接和包含。 我还必须从连接中删除:locations_current关联。 它试图通过尝试来制造一些混乱
... LEFT OUTER JOIN `locations` ON `location_histories`.current = 1 ...
这当然不是一个有效的关联。 似乎“当前”条款已被转移到JOINS中。
所以现在我有以下,这是有效的。
@people = Person.joins([[:locations=>:location_hour],:friends]).includes([[:locations=>:location_hour],:friends]).where("(location_histories.current = true) AND (people.name LIKE ? OR friends.first_name LIKE ? OR friends.last_name LIKE ? OR (friends.first_name LIKE ? AND friends.last_name LIKE ?))")
综上所述:
1)我需要使用连接和包含来加载和正确解释.while()条件
2)我需要在joins子句中保持与条件(即:current_locations)的关联。
如果这对你来说似乎是一个明显的错误,请纠正我。 它似乎工作。 这将活动记录时间降低到不到1秒。
组合连接和包含是否常见?
谢谢!
我已经找到问题的一部分(虽然仍有一些意想不到的行为)。 我有几个范围,例如locations.current,如上所述定义。
我把这个逻辑移到了协会。 所以在我的Person模型中,我现在有了
has_many :current_locations, :source => :location, :through => :location_histories, :conditions => ["`location_histories`.current = ?", true]
我打电话
Person.current_locations.first
代替
Person.locations.current.first.
因此,现在包含按预期进行急切加载。
问题是这搞砸了搜索。 出于某种原因,当我包含where子句时,现在一切似乎都挂起了。 对于我添加到include中的每个表,当我包含所有必要的表时,事情首先变得非常慢。 没有错误。
我知道这一点:当我在where子句中添加符号时,Rails在查询期间执行外连接(如此处所述),这是预期的。 但是为什么这会导致整个事情崩溃?
(这里的一个小问题是我需要字符串比较。为了得到一个正确的连接我打电话。在哪里
.where(:table =>{:column=> 'string'})
这相当于
table.column = 'string'
在SQL但我需要
table.column LIKE '%string%'
奇怪的是,对我来说,我得到以下行为:
# fails to eager load tags--it only loads one of the tags for me, instead of all of them. Product.find(:all, :conditions => ["products_tags.tag_id IN (?)", 2], :include => [:tags])
但这成功了
Product.find(:all, :conditions => ["products_tags.tag_id IN (?)", 2], :include => [:tags], :joins => [:tags])
这就像内连接表上的查询以某种方式搞乱了急切的加载。 所以你的答案可能是正确的。 但这里可能有些奇怪的事情发生。 (这里是Rails 2.3.8)。