我正在实施一个包含帖子和可投票评论的博客。
加载帖子时,我想急切加载当前用户对帖子评论的所有投票。
这样的东西(不起作用):
@post.comments.all(:joins => :votes, :conditions => ['votes.user_id = ?', current_user.id])
每个评论都有一个名为 rated_by?
的方法def rated_by?(actor)
votes.find_by_user_id(actor.id)
end
问题是ActiveRecord会为每个rated_by运行一个查询吗?打电话,即使我的@ post.comments finder加入了所有相关的投票。
我看了一下act_as_rateable插件,但它有同样的问题,为每条记录运行查询,而不是使用连接。
答案 0 :(得分:3)
双重秘密编辑:我正在回答另一个问题并遇到了一些适合你的事情。这是涉及Thread.current全局哈希的一个疯狂的黑客攻击。可能根本没有建议,但它确实有效。
它涉及在评论
上创建第二个has_many投票关联class Comment < ActiveRecord::Base
has_many :votes
belongs_to :post
has_many :current_user_votes, :class_name => "Vote",
:conditions => '`#{Vote.table_name}`.user_id = \
#{Thread.current[:current_user].id}'
end
它还要求您在要调用这些方法的控制器中设置Thread.current [:current_user] = current_user。
然后你应该能够做到
@post.comments.find(:all, :include => :current_user_votes)
要获取注释列表,只需加载:current_user_votes。一站式查询。如果您一次收到多个帖子,则可以执行此操作。
Post.find(:all, :include => { :comments => :current_user_votes},
:conditions => ...)
将填充一个帖子列表,并急切加载他们的评论,这些评论反过来每个人都会加载他们的current_user_votes。
原始答案(为子孙后代保留)
我认为在一个查询中只能选择一个模型急切加载所有相关关联。
你将获得的最好成就就是你所做的。选择所有一个模型,然后为每个模型仅加载与命名范围或查找器的相关关联。
这个不起作用的声明只是选择用户投票的评论。
@post.comments.all(:joins => :votes,
:conditions => ['votes.user_id = ?', current_user.id])
此语句选择同一组注释,但也会为所选注释加载所有投票。
@post.comments.all(:include => :votes,
:conditions => ['votes.user_id = ?', current_user.id])
你真正需要做的就是打电话给rated_by?在每个评论。您可以通过使用命名范围来最小化数据库影响。但老实说,我认为它不会有所改善。
如果你非常担心如此努力地打击数据库,你可以这样做:
class Post < ActiveRecord::Base
has_many :comments
has_many :votes, :through => :comments
...
end
class Vote < ActiveRecord::Base
belongs_to :comments
...
named_scope :made_by_user, lambda {|user|
{:conditions => {:user_id => user}}
}
end
@users_votes = @post.votes.made_by_use(current_user)
@comments = @post.comments.find(:all, :include => :votes)
@comments.each{|comment|
user_voted_this_on_this_comment = comment.votes & @user_votes
...
}
老实说,我认为值得付出努力。
P.S。有一个关于方法名称的Ruby约定,以问号结尾应始终返回一个布尔值。
答案 1 :(得分:1)
你需要使用
:include => :votes
连接不加载您的数据,它只是加入数据库中的查询。