2012-07-04 46 views
1

我有一个用户,帖子和评论的应用程序。用户has_many帖子,帖子has_many评论和意见belongs_to用户和帖子。Rails寻找关联的效率

在我看来模板我遍历这样的评论让评论者的用户名:

User.find(comment.user_id).name

效率如何这一点,如果我这样做是为每个职位每个评论? 我可以想象,将注册表中的用户名存储在单独的行中可能会更快,但是重复数据似乎只是错误的。

我是不是偏执狂,是ActiveRecord做一些缓存魔术还是有更好的方式做这样的事情吗?

回答

0

您可以在初始查询预加载的用户。 鉴于用户和评论之间的关联设置,您可以通过关联访问用户。

让我们假设你有一个控制器方法:

def show 
    @posts = Post.limit(10).includes(:comments => :user) 
end 

在你看来,你遍历@comments

@posts.each do |post| 
    # show post stuff 
    post.comments.each do |comment| 
    comment.user.name 
    end 
end 
+0

因此,如果我限制返回的帖子(比如10),那么'@ comments'只会抓取10个返回帖子的用户? – DeanAlexRainier

+0

@daanVOS我更新了我的例子。这会加载10个帖子,包括评论和评论用户全部热切。 – lebreeze

+0

@daanVOS通过这种方式,应用程序可能会为帖子提供一个SQL查询,一个用于评论,另一个用于发表评论的用户,无论有多少评论。 – lebreeze

0

Eager loading of associations

class Post < ActiveRecord::Base 
    has_many :comments 
    # ... 
end 

class Comment < ActiveRecord::Base 
    belongs_to :user 
end 


comments = @post.comments.includes(:user) 

它将预装用户。

SQL看起来像:

SELECT * FROM `comments` WHERE `comments`.`post_id` = 42; 
SELECT * FROM `users` WHERE `users`.`id` IN (1,2,3,4,5,6) # 1,2,3,4,5,6 - user_ids from comments 
+0

但后来我不得不提出另一个请求来获取帖子... – DeanAlexRainier

+0

你的意思是你想加载与评论用户与用户的帖子的帖子? – cutalion

0

修订

如果您有关联作为下面你可以访问用户来自评论对象本身comment.user

class User < ActiveRecord::Base 
    has_many :posts 
    has_many :comments 
end 

class Post < ActiveRecord::Base 
    belongs_to :user 
    has_many :comments 
end 

class Comment < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :post 
end 
+0

这是不是说评论用户与评论相关联的帖子的所有者相同?在这种情况下,这是完全错误的,因为许多用户可以评论其他用户的帖子? – lebreeze

+0

@lebreeze,我有同样的问题 – cutalion

+0

让我纠正它...... – Bongs

0

如果性能对您而言是个问题,那么使用非关系型数据库(如Mongodb)是一条可行之路。

如果你仍然想使用ActiveRecord,无论您使用Post.comments.include(:user)预先加载(这将加载未使用的用户信息 - 这不是很大),也可以使用缓存技术。

只要您控制可能发生的更改,我发现可以按照您的建议将user.name缓存在评论表中。你可以通过在你的User模型设置回调:

after_save do |user| 
    Comment.where(user_id: user.id).update_all(:username, user.name) 
end 

这种技术是不大不小的DB缓存,但是,当然,你可以缓存HTML片段。并且注释块对于缓存HTML块是一件好事。