用户(has_many :user
,has_many :comments
)
发帖(belongs_to :user
,has_many :comments
)
评论(belongs_to :user
,belongs_to :post
)
现在我正在尝试检索所有帖子(至少有一条用户评论)更新了该帖子中用户的上一条评论的评论(我将使用用户的updated_at属性)
示例: 发布A
用户X,Y
X在A
中发表评论然后Y在A
中发表评论现在我想要检索帖子A,因为在用户X的最后评论之后在A中发布了新评论。
同样,我想检索在用户评论后发布评论的所有帖子。
(每次他在任何帖子中发表评论时,我都更新了updated_at
用户的值
(我还更新了帖子的updated_at
值,每次有人发布帖子中的评论)
我已经了解了如何在RoR中实现这一目标,但是没有任何线索,所以最后我转而在StackOverflow中提供帮助:)
先谢谢你们
答案 0 :(得分:0)
SQL魔术:
class User
def posts_with_comments_since_my_last_comment_in_that_post
Post.find_by_sql([%Q| SELECT DISTINCT posts.* from posts INNER JOIN users on
(posts.user_id = users.id) INNER JOIN comments on
(comments.user_id = users.id AND comments.post_id = posts.id)
WHERE (posts.updated_at > comments.updated_at) AND (users.id = ?)|, id])
end
def posts_with_comments_since_my_last_comment
Post.find_by_sql([%Q| SELECT DISTINCT posts.* from posts INNER JOIN users on
(posts.user_id = users.id) INNER JOIN comments on
(comments.user_id = users.id AND comments.post_id = posts.id)
WHERE (posts.updated_at > user.updated_at) AND (users.id = ?)|, id])
end
end
您可以通过创造性地使用缓存来避免这种情况,但我不会建议。 确保您的表格已正确编入索引。如果您运营的网站包含大量评论,则可能会非常非常错误。
答案 1 :(得分:0)
以下内容不起作用,因为您尝试在Comment对象上获取帖子。
@post_ids = Comment.all(:select => "DISTINCT post_id",
:conditions => ["user_id = ? AND updated_at > ?",
@userinfo.id, @userinfo.updated_at.to_date.to_time])
@posts = Post.find(@post_ids)
您可以将所有评论映射到帖子ID。
即:Post.find(@post_ids.map{&:post_id})
但这样效率低,需要两次数据库访问并实例化命中注释。
相反,您应该使用命名范围或某些内容根据您的条件选择帖子。
class Post < ActiveRecord::Base
...
#this is what you asked for.
named_scope :with_unseen_comments_for_user, lamda do |user|
{
:select => "DISTINCT posts.*", :joins => "INNER JOIN comments,
comments others_comments, users ON (comments.user_id = users.id AND
others_comments.post_id = post.id AND comments.post_id = posts.id",
:conditions => ["users.id = ? AND
comments_posts.updated_at > users.updated_at", user]
}
end
end
#usage:
Post.updated_after_users_last_comment_in_post(@user)
创建高效查询需要复杂的连接语句,因为您希望连接工作列表:
其他评论&lt; --- post_id - id ---&gt;帖子&lt; --- id - post_id ---&gt;用户评论&lt; --- user_id - id ---&gt;用户
假设我的SQL是我记忆中的,那么这应该检索给定用户评论的所有帖子,并且他的最后一篇帖子是在同一帖子上的其他评论之前发布的。
无论如何,当用户在多个线程中发帖时,您将遇到问题。所以你可能想重新考虑你的关系并更新方法。
例如,如果发生以下情况,您的用户将不会收到有关帖子A的新评论的通知:
用户X对帖子A的评论
用户Y对帖子A的评论
在注意到用户Y对帖子A发表评论之前,用户X对帖子B发表评论。
您可以通过在评论中添加last_seen_at字段来解决此问题,并在所有者查看评论时对其进行更新。这对于:after_filter来说相当微不足道。事实上,它使命名范围更加简单。因为我们不需要将用户记录拖到查询中来比较日期。
named_scope :unseen_comments, lamda do |user|
{
:select => "DISTINCT posts.*", :joins => [:comments, :comments],
:conditions => ["comments.user_id = ? AND
others_comments.updated_at > comments.last_seen_at", user]
}
end
:joins => [:comments, :comments]
有点奇怪,但它会将评论加入查询中的帖子两次,第二次将其别名为comments_posts。它没有在find或named_scope中具体记录,但它使用与关联连接参数相同的语法。