2011-04-04 59 views
1

我的代碼的has_many/belongs_to的關聯導致翻一番查詢

class Magazine < ActiveRecord::Base 
    has_many :ads 
end 

class Ad < ActiveRecord::Base 
    belongs_to :magazine 
end 

我有類似的東西在我的代碼如下(假設params[:magazine_name]params[:ad_name]):

mag = Magazine.find_by_name(params[:magazine_name]) 
@ad = mag.ads.find_by_name(params[:ad_name]) 

如果我現在訪問@ad.magazine ,它使存儲在@ad中的雜誌ID發現另一個數據庫查詢。爲什麼ActiveRecord沒有足夠的智能來實現它已經從數據庫獲得它,它不應該再次得到它? (我該如何讓它更聰明?)

回答

2

它不夠智能的原因是因爲ActiveRecord在默認情況下不使用標識映射模式。據傳該解決方案爲using :inverse_of on your relationships

+0

謝謝。據燈塔(和我的測試),這是目前打破,但它有望在不久的將來修復。 – 2011-04-07 21:40:54

+0

(鏈接:https://rails.lighthouseapp.com/projects/8994/tickets/4914-activerecord-inverse_of-doesnt-have-any-effect) – 2011-04-29 16:39:28

+0

看起來它會在3.1中修復:http:// edgerails .info/articles/what-s-new-in-edge-rails/2011/04/21/activerecord-identity-map/index.html – 2011-05-08 00:28:14

0

您想要做一些名爲「急切加載」的地方,您可以繼續前進,並加載您很快就會知道的關聯。要做到這一點的方式是固定導軌2之間的不同和Rails 3

在Rails 3,您使用.includes方法:

Ad.includes(:magazine).find_by_name(params[:ad_name]) 

在軌道2,您可以使用:包括哈希:

Ad.find_by_name(params[:ad_name], :include => [:magazine]) 
+0

雖然這是一個好主意,並將查詢數從N + 1減少到1 ,這實際上並不是OP所要求的。 – nickgrim 2011-04-04 14:22:14

+0

它不怎麼樣?他希望能夠在不產生新的數據庫查詢的情況下執行@ad.magazine,這就是它的作用。 – 2011-04-04 14:30:06

+0

但是我在找到廣告之前已經加載了雜誌;它應該認識到這一點並回收參考。 – 2011-04-04 19:16:09