Rails查询关联的模型范围

时间:2017-04-04 13:59:06

标签: ruby-on-rails activerecord scopes associated-object

我正在努力为一项简单的任务寻找合适的解决方案。基本上我有类别模型有很多 帖子帖子属于类别

我将类别显示为搜索表单的一部分以及其他一些地方,并且不希望显示没有关联帖子的类别。这似乎毫无意义。

我设法通过在类别模型中添加以下方法来解决此问题。

# Check if Category has associated results
def self.with_results
  includes(:posts).where.not(posts: { id: nil })
end

这很好,允许我过滤没有结果的类别。当我尝试使用范围时,稍微混淆一点。

我的帖子有几个范围,例如frontend_visible,它决定是否应该从前端(非管理员)访问它。

scope :frontend_visible, -> { where(:state => ['approved', 'changes_pending_approval']) }

同样,我还有其他范围来提取仅标记为私人内容的帖子(仅限会员)。

我最初的解决方案的问题是,包含未经批准的帖子的类别将不会显示,同样非成员将无法看到标记为私人的帖子,尽管仍会显示该类别。

理想的解决方案是:

获取所有具有相关帖子的类别,如果关联的帖子不是前端可见,则忽略类别。如果current_user无法访问私有内容,并且所有关联的帖子都标记为私有,则忽略类别。

我有范围,但我不确定如何从相关模型中使用它们。这可能吗?

1 个答案:

答案 0 :(得分:1)

据我了解,您需要选择包含用户可见的帖子的类别。为此你需要做两件事:

  1. 在用户的角色和帖子的可见范围之间进行映射
  2. 为用户可见的帖子选择类别。在您的情况下,在两个查询中选择不带连接的类别会更容易。
  3. 试试这段代码:

    class Category < ApplicationRecord
      has_many :posts
    
      scope :with_posts_for_user, -> (user) do
        where(id: Post.categories_for_user(user))
      end
    end
    
    class Post < ApplicationRecord
      belongs_to :category
    
      scope :frontend_visible, -> { where(:state => ['approved', 'changes_pending_approval']) }
      scope :member_visible, -> { where(:state => ['approved', 'changes_pending_approval', 'private']) }
    
      scope :categories_for_user, -> (user) do
        (user.member? ? member_visible : frontend_visible).distinct.pluck(:category_id)
      end
    end