2012-03-10 44 views
19

我正在運行Ruby on Rails 3.1。我閱讀下面的文章和文檔有關預先加載,我想找個做的事情正確的方法:渴望加載:正確的做事方式

  1. Eager Loading Associations【官方文檔】
  2. ActiveRecord::Associations::ClassMethods(請參見「聯想的預先加載」 )【官方文檔】
  3. Eager loading [博客文章]

#2說:

注意使用條件像Post.includes([:作者:評論])。其中([ '?comments.approved =',真])所有可以產生意想不到的後果。

#3說,這些意想不到的後果是:(:例子是很相同的,所以我引用的博客文章的確切內容,但你必須記住具體的解決辦法,而不是執行):

這個查詢,因爲它會使用一個LEFT JOIN,所以也會放棄所有沒有任何評論的單詞「first」的評論。

也就是說,如果存在非「關聯」對象,則「主關聯」對象將不會被加載。當我嘗試使用加入一些條件.where(:category_relationships => {:user_id => @current_user.id})在我的previous question時,會發生這種情況,但我不希望發生這種情況。

所以(失敗主義者,因爲我可能不能在我的情況下條件不能在has_many語句設置使用預先加載 - 請注意,在上面的代碼@current_user.id是存在於例子「動態設置」不像我想知道是否有pratiques /技術/戰略,以限制數據庫查詢,因爲我有一個「N + 1問題」

也許這些pratiques /技術/策略是通過使用Ruby on Rails框架的所有可執行...的#1說:

即使活動記錄可以讓你在渴望 指定條件像加入一樣加載關聯,推薦的方法是使用 連接。

什麼和如何解決這個問題的正確方法?


可能的解決方案是檢索和建立自己需要運行特定分離數據庫查詢裝載什麼,但隨後的問題就如何「通」 /「副」 /「插值」那些將「關聯」對象檢索到「主要關聯」對象,以便那些可以使用「一種渴望加載」的方式?也就是說,如何使可能(請參閱mentioned question獲取更多信息)使用類似@article.comments之類的代碼,並只獲得我渴望加載自己的評論? 我的渴望加載,是否可能/正確使類似@article.comments = my_eager_loaded_comments這樣「傳遞」/「關聯」/「插值」評論文章?

回答

2

從#2 ActiveRecord::Associations::ClassMethods談到這一點:

如果你想急於負荷只有一個協會的一些成員是 通常更自然包括上定義條件 關聯:

class Post < ActiveRecord::Base 
    has_many :approved_comments, 
    :class_name => 'Comment', 
    :conditions => ['approved = ?', true] 
end 

Post.includes(:approved_comments) 

這將加載信息,並渴望負荷approved_comments協會, 其中包含3個只有那些已被批准的評論。

如果我理解這個正確的情況下,有一個不確定性,當你申請。凡()到主查詢與包括()和AR的地方適用於整個查詢限制你的原則,結果那些有合格的關聯謂詞。但是,如果您將謂詞的範圍僅限於上述關聯,那麼AR理解並給出所有原則結果以及與謂詞條件相匹配的相關對象。

+3

因爲在我的情況下,我不能使用'has_many'關聯,因爲在我的情況下,我應該說''has_many,:conditions => ['user_id =?',@ current_user.id]'(*這是不可能的!* ...當然是我的知識)。因此,我想知道有關急切加載功能的解決方案。 – Backo 2012-03-12 23:54:04

6

我渴望加載後,是有可能的/正確的做出像@ article.comments = my_eager_loaded_comments所以要「通」 /「副」 /「插值」評論文章?

是的,這是可能的。我經常這樣做。

請注意,我的解決方案仍然從數據庫中檢索所有關聯的對象。如果條件是動態的,我認爲沒有任何解決方法可以檢索過濾的關聯對象。我的解決方案關注於檢索的關聯對象的過濾。

我假設的要求是get a list of articles和每篇文章eager load the comments of only one particular user

Article模式:

def self.get_articles_with_comments_of_user(article_ids, user_id) 
    articles = Article.where(id: article_ids).includes(:comments) 

    articles.each do |article| 
    filtered_comments = article.comments.select { |comment| comment.user_id == user_id } 
    article.association("comments").target = filtered_comments 
    end 

    articles 
end 

在通過上述方法返回文章收藏,評論協會將有特定用戶的唯一的意見。

我希望這是你要求的。

+0

「如果條件是動態的,我認爲沒有任何解決方案可以檢索過濾的關聯對象。」 - 也許[這](http://stackoverflow.com/a/15543228/867305)是解決方案? – thejaz 2013-03-21 09:24:23

+0

在鏈接的答案中,我沒有看到任何動態條件傳遞過濾急切加載。我可能會理解錯誤。這個答案只是描述了一個普通的'has_many:through'關聯。在這個問題的背景下如何使用這個解決方案? – Anjan 2013-03-22 06:49:38