两个模型(Rails 2.3.8):
我正在尝试创建一个named_scope来消除disabled = 1和hidden = 1 User-Profiles。 User模型通常与Profile模型一起使用,因此我尝试加载Profile模型(:include =>:profile)。
我在User模型上创建了一个名为'visible'的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时,会忽略eager-loading指令。
变体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 - 在视图中使用Profile模型;延迟加载配置文件模型
# 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是否更好地处理了这种情况?
答案 0 :(得分:4)
来自railsapi.com:
急切加载关联
[...]因为只加载了一个表 一次,条件或订单 不能引用除了以外的表 主要的。如果是这样的话 记录回落到之前 使用LEFT OUTER JOIN策略。 例如
Post.find(:all, :include => [ :author, :comments ], :conditions => ['comments.approved = ?', true])
将导致单个SQL查询 加入:LEFT OUTER JOIN评论评论.post_id = posts.id和LEFT OUTER JOIN作者 ON authors.id = posts.author_id。
我相信这会回答您的问题...“变体#4”中没有急切的加载,因为您引用了profiles
上的named_scope
表格。
答案 1 :(得分:0)
我相信以下内容可能会为您提供所需内容:
@users = User.visible.scoped(:include => :profile)
这对我来说很有用,但是我没有在命名范围的定义中加入其他表。
Jim Benton在他的博客上提供了一种优雅的方式将其添加到ActiveRecord:http://autonomousmachine.com/posts/2009/10/28/add-a-scope-for-easier-eager-loading