2011-05-11 101 views
0

我正在Rails 3.0.7中工作。Rails 3拒絕急切加載

我有不急於負載一些多到很多,有一種-to-many關聯。

我的聯繫是:

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 

然後在我的觀點,我有:

<% @people.each do |person| %> 
    <tr> 
    <td><%= link_to person.name, person %></td> 
    <td><%= link_to person.friends.collect {|s| [s.full_name]}.join(", "), person.friends.first %></td> 
    <td><%= link_to person.locations.current.first.name, person.locations.current.first %></td> 
    </tr> 
<% end %> 

locations.current是一個範圍定義爲:

scope :current, lambda { 
    where("location_histories.current = ?", true) 
} 

可正常工作和第2個生成數據庫調用:一個拿到個人ID的列表,然後一個大的數據庫調用,一切都是正確連接。問題是,後有n個數據庫的線沿線的來電:

SELECT 'friends'.* from 'friends' WHERE ('friends'.person_id = 12345) 

所以對於在視圖中循環的每個迭代。不用說這需要一段時間。

我以爲。所有將迫使預先加載。任何人都知道這裏發生了什麼?
這花費超過3秒的ActiveRecord。太長了。

我將不勝感激任何和所有的建議。

謝謝。

+0

我以前在<= 3.0.3和急切加載時遇到了問題。是否可以嘗試升級到3.0.7? – Dex 2011-05-11 23:45:10

+0

謝謝Dex。將嘗試並報告。 – NAD 2011-05-12 02:48:56

+0

已升級到3.0.7,仍然有相同的問題。 – NAD 2011-05-12 03:20:16

回答

1

確定。終於解決了。
我需要調用連接和包括。我還必須從連接中刪除: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)我需要使用兩個連接,並且包括用於立即加載和。而的正確解釋()條件
2)I需要保持與條件(即關聯:current_locations )不在連接子句中。

請糾正我,如果這似乎是一個明顯的錯誤給你。它似乎工作,但。這將活動記錄時間降低到不到1秒。

結合連接幷包含它是否很常見?

謝謝!

0

我已經想通了這個問題的一部分(雖然還是有一些意想不到的行爲)。 我有幾個範圍,如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子句時,所有東西似乎都會掛起。每次添加到包含表的時候,事情首先會慢得多,到時候我只包含所有必要的表。沒有錯誤。

我的確知道這一點:當我在where子句中添加符號時,Rails在查詢過程中執行外連接(如解釋here),這是預期的。但爲什麼這會導致整個事情崩潰?

(這裏的一個小問題是,我需要字符串比較。爲了得到適當加入我打電話。其中,作爲

.where(:table =>{:column=> 'string'}) 

這相當於

table.column = 'string' 

在SQL,但我需要

table.column LIKE '%string%' 
0

奇怪的是,對我來說,我得到了以下行爲:

# 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)。