2010-06-13 75 views
2

兩個模型(滑軌2.3.8):軌named_scope忽略預先加載

  • 用戶;用戶名&禁用屬性;用戶has_one:個人資料
  • 個人資料;全名&隱藏屬性

我想創建一個名爲_scope消除殘疾= 1和隱藏= 1用戶配置文件。 User模型通常與Profile模型一起使用,因此我試圖加載Profile模型(:include =>:profile)。

我創建的用戶模型named_scope稱爲「看得見」:

named_scope :visible, { 
    :joins => "INNER JOIN profiles ON users.id=profiles.user_id", 
    :conditions => ["users.disabled = ? AND profiles.hidden = ?", false, false] 
} 

我注意到,當我用named_scope在查詢時,急於加載指令被忽略。

變形例1 - 用戶模型只:

# UserController 
@users = User.find(:all) 

# User's Index view 
<% for user in @users %> 
    <p><%= user.username %></p> 
<% end %> 

# generates a single query: 
SELECT * FROM `users` 

變形例2 - 用剖面模型在圖;延遲加載剖面模型

# UserController 
@users = User.find(:all) 

# User's Index view 
<% for user in @users %> 
    <p><%= user.username %></p> 
    <p><%= user.profile.full_name %></p> 
<% end %> 

# generates multiple queries: 
    SELECT * FROM `profiles` WHERE (`profiles`.user_id = 1) ORDER BY full_name ASC LIMIT 1 
    SHOW FIELDS FROM `profiles` 
    SELECT * FROM `profiles` WHERE (`profiles`.user_id = 2) ORDER BY full_name ASC LIMIT 1 
    SELECT * FROM `profiles` WHERE (`profiles`.user_id = 3) ORDER BY full_name ASC LIMIT 1 
    SELECT * FROM `profiles` WHERE (`profiles`.user_id = 4) ORDER BY full_name ASC LIMIT 1 
    SELECT * FROM `profiles` WHERE (`profiles`.user_id = 5) ORDER BY full_name ASC LIMIT 1 
    SELECT * FROM `profiles` WHERE (`profiles`.user_id = 6) ORDER BY full_name ASC LIMIT 1 

變形例3 - 急於負載資料模型

# UserController 
    @users = User.find(:all, :include => :profile) 

    #view; no changes 

    # two queries 
    SELECT * FROM `users` 
    SELECT `profiles`.* FROM `profiles` WHERE (`profiles`.user_id IN (1,2,3,4,5,6)) 

變形例4 - 使用name_scope,包括急切裝載指令

#UserConroller 
    @users = User.visible(:include => :profile) 

    #view; no changes 

    # generates multiple queries 
    SELECT `users`.* FROM `users` INNER JOIN profiles ON users.id=profiles.user_id WHERE (users.disabled = 0 AND profiles.hidden = 0) 
    SELECT * FROM `profiles` WHERE (`profiles`.user_id = 1) ORDER BY full_name ASC LIMIT 1 
    SELECT * FROM `profiles` WHERE (`profiles`.user_id = 2) ORDER BY full_name ASC LIMIT 1 
    SELECT * FROM `profiles` WHERE (`profiles`.user_id = 3) ORDER BY full_name ASC LIMIT 1 
    SELECT * FROM `profiles` WHERE (`profiles`.user_id = 4) ORDER BY full_name ASC LIMIT 1 

變形例4確實返回正確的數的記錄,但也似乎忽略了急切的加載指令。

這是跨模型命名範圍的問題嗎?也許我沒有正確使用它。

Rails 3能夠更好地處理這種情況嗎?

回答

4

railsapi.com

協會預先加載

[...]由於只有一個表在時間加載 ,條件或命令 不能引用比其它表 主要一個。如果是這樣的話主動 記錄回落到之前的 使用基於LEFT OUTER JOIN的策略。 例如

Post.find(:all, :include => [ :author, :comments ], :conditions => ['comments.approved = ?', true])

將導致一個SQL查詢與 線沿線的聯接:LEFT OUTER JOIN ON comments.post_id = posts.id和LEFT OUTER JOIN評論作者 ON作者。 id = posts.author_id。

我相信這個回答你的問題...有一個在「變化#4」沒有預先加載,因爲你引用您named_scopeprofiles表。

+0

確定。我可以將隱藏屬性移動到用戶模型中,以完全避免這種情況,但最好爲此類情況找到另一種方法。你能想到一個嗎? – craig 2010-06-14 02:14:33

+1

您可以創建另一個關聯:「用戶has_one:visible_profile」。然後你調用@ user.visible(:include =>:visible_profile),當'visible'是隻有這個條件的named_scope時:'[「disabled =?」,false]'。這就像'railsapi.com'上的例子。 – 2010-06-14 11:49:18

+0

@j:我添加了一個關聯到用戶模型 - has_one:visible_profile,:class_name =>'Profile',:conditions => [「profiles.hidden =?」,false]。更改了用戶模型的named_scope --name_scope:visible,{ :conditions => [「disabled =?」,false] } UserController的索引操作已更改 - @users = User.visible(:all,:include =>:visible_profile) 。重新啓動服務器。延遲加載仍在發生。 Profile-model過濾器被忽略。思考? – craig 2010-06-14 13:14:30