2013-07-12 83 views
0

我有這樣的has_many關係:的has_many關係重載父

class Event < ActiveRecord::Base 
    has_many :event_rows 
    ... 
end 
class EventRow < ActiveRecord::Base 
    belongs_to :event 
    ... 
end 

當我運行下面的代碼片段,它告訴我36個查詢:

@events = Event.where("date = ?", @date).all 
@events.each do |e| 
    first = e.event_rows.first 
    first.event 
end 

當我運行這個片段中,我只得到19查詢

@events = Event.where("date = ?", @date).all 
@events.each do |e| 
    first = e.event_rows.first 
    first.event = e # forcing the parent 
    first.event 
end 

我做錯了什麼,或者rails每次運行一個查詢EventRow都會詢問它s事件?

在迴應評論:查詢是不標記爲CACHED:

SQL (0.7ms)[0m SELECT "event_rows"."id" AS t0_r0, "event_rows"."event_id" ... WHERE "event_rows"."event_id" = 1 LIMIT 1 
Event Load (0.6ms)[0m [1mSELECT "events".* FROM "events" WHERE "events"."id" = 1 LIMIT 1[0m 
SQL (3.2ms)[0m SELECT "event_rows"."id" AS t0_r0, "event_rows"."event_id" ... WHERE "event_rows"."event_id" = 2 LIMIT 1 
Event Load (0.5ms)[0m [1mSELECT "events".* FROM "events" WHERE "events"."id" = 2 LIMIT 1[0m 
+0

我想這36個查詢中的大部分都被標記爲緩存在日誌中,不是嗎? –

+0

我現在試過了,它們沒有標記爲緩存。 – carlosvini

+0

啊,這是在發展?在開發中默認禁用模型緩存,這可能是原因 –

回答

1

我偶然發現了問題的答案。

看來你可以使用inverse_of選項,以防止同一個實例:

沒有:inverse_of m和f.man將(從數據庫中被拉到f.man再次對同一對象的不同實例)。有了這些新功能:inverse_of選項m和f.man在內存實例中是相同的。

+0

我很難理解爲什麼這不會是一種默認行爲,但在我看來,不僅缺乏inverse_of效率可能非常低,還會在沒有它的情況下在代碼中出現一些令人討厭的錯誤。 –

+0

有經驗的rails開發人員習慣了它,並避免錯誤本能地將代碼移到父級或子級,具體取決於錯誤發生的可能性。由於我是初學者,我不習慣它。我認爲他們應該儘可能早地違反默認行爲,不是因爲性能,而是因爲所有的初學者都假定child.parent是父母在調用parent.children.first時的同一個實例。 – carlosvini

0

與邁克爾Szyndel同意,模型緩存可能在發展被禁用,還我相信你想更新你的代碼如下,

@events = Event.includes(:event_rows).where(date: @date) 
@events.each do |e| 
    # your code 
end 

我不認爲你需要all,這裏包括哪些重要的事情將包括哪些將加載event_rows。

希望它會幫助..

+0

我在這裏發佈的代碼不是真正的代碼,它只是我發現重現錯誤的最簡單的方法。我已經在使用includes(:event_rows)。在真正的代碼中,我沒有調用。首先,我有公式,他們碰巧調用event_row.event,我發現它正在運行一個查詢,因爲event_rows已經包含我假設event_row.event應該已經是填充。無論如何,我在我的代碼中創建了一個解決方法。只是想知道這是否是默認的導軌行爲。它可能是'更聰明',並保持event_row.event填充。 – carlosvini