我有一个用户,帖子和评论的应用程序。用户has_many帖子,帖子has_many评论和评论belongs_to用户和帖子。
在我的视图模板中,我循环遍历这样的评论以获取评论者的用户名:
User.find(comment.user_id).name
如果我为每个帖子的每个评论做这个,效率有多高? 我可以想象,将用户名存储在Comments表的单独行中可能会更快,但重复数据似乎是错误的。
我是偏执狂吗?ActiveRecord正在做一些缓存魔法,还是有更好的办法做这样的事情?
答案 0 :(得分:0)
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
答案 1 :(得分:0)
您可以在初始查询中预加载用户。 看到您在User和Comment之间建立了关联,您可以通过关联访问用户。
假设你有一个控制器方法:
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
答案 2 :(得分: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
答案 3 :(得分: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
这种技术有点像数据库缓存,当然,你可以缓存HTML片段。并且注释块可以缓存HTML块。