获取rails /范围的补充,过滤掉匹配的条目

时间:2010-11-02 16:55:10

标签: ruby-on-rails-3 scope inverse

我正在构建一个模型,用于跟踪给定用户已阅读的帖子(在Rails 3中)。跟踪这个的表是'读数'。阅读belongs_to both:user和:post,两者都有has_many:读数。当用户看到帖子时,它被标记为已读,并且使用user_id和post_id创建“阅读”。这似乎工作正常,但现在我正在尝试编写一个范围,只返回给定用户的未读帖子。查找阅读帖子可以正常工作:

scope :read, lambda { |user_id = nil |       
    user_id.nil? ? {} : joins(:readings).where('readings.user_id = :user_id', :user_id => user_id)
}

然而,我尝试返回此集的补充(未读帖子)失败。如何才能做到这一点?是否有一种通用的方法来编写一个只返回另一个(这里,:read)的补集的范围(方法)?我也很乐意把它写成一个与作用域相同的类方法。

请记住,只有在阅读帖子时才会创建读数,因此新帖子将没有读数。这似乎比为每个新帖子为每个用户创建条目更经济。

编辑:好的,我越来越近了 - 下面的范围几乎可以工作,但不要求帖子的所有读数都不等于user_id。因此,如果用户#1已经阅读了帖子,并且用户#2也是如此,那么查询其他阅读并发现它们不相等。所以这个帖子被错误地发现是未读的。

scope :unread, lambda { |user_id = nil |       
    user_id.nil? ? {} : includes(:readings).where('(readings.user_id IS NULL OR readings.user_id != :user_id)', :user_id => user_id)
}

1 个答案:

答案 0 :(得分:0)

嗯,看起来如下工作。仍在测试。如果有人在这里发现一个洞,很高兴重新开放。

scope :unread_by, lambda { |user_id = nil, hide_unread = nil|
      { :joins => "LEFT JOIN readings ON  readings.post_id    = post.id
          AND readings.user_id        = #{user_id}",
          :conditions => 'readings.id IS NULL' }
}