【问题标题】:Conditions on has_many in Rails 4.2?Rails 4.2 中 has_many 的条件?
【发布时间】:2016-06-11 15:30:47
【问题描述】:

我有一个 Post 模型,它有一个 has_many :authors 和 has_many :tags 到 :tag_posts,一个 Author 模型有一个 has_many :posts 和 has_many :tags 到 :posts,一个 Tag 模型有一个 has_many :posts 到 :tag_posts。

帖子必须通过审核(存储为枚举 Post.status)才能在网站上显示。版主可以通过查找具有不同 Post.status 的帖子来查看未经审核的帖子,但普通用户应该永远无法看到它们。

有什么方法可以过滤所有这些关联以确保它们只返回版主批准的帖子?

例如:如果我现在调用 Author#tags,它将返回作者撰写的所有帖子上的所有标签,但我只希望它返回 已批准 帖子上的标签作者写过。假设作者有两个帖子,第一个已批准并标记为“章鱼”,第二个尚未批准并标记为“鱿鱼”:对该作者调用#tags 应该只返回章鱼标签,而不是鱿鱼标记。

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-4 activerecord


    【解决方案1】:

    我有一个 Post 模型,它有一个 has_many :authors 和 has_many :tags 到 :tag_posts,一个 Author 模型有一个 has_many :posts 和 has_many :tags 到 :posts,一个 Tag 模型有一个 has_many :posts 到 :tag_posts。

    首先,让我们整理一下这些关系。我相信这是您真正想要的:

    class Post < ActiveRecord::Base
      belongs_to :author  # NOT has_many
      has_and_belongs_to_many :tags # use an implicit join table
    end
    
    class Author < ActiveRecord::Base
      has_many :posts
    end
    
    class Tag < ActiveRecord::Base
      has_and_belongs_to_many :posts # use an implicit join table
    end
    

    有什么方法可以过滤所有这些关联,以确保它们只返回版主批准的帖子?

    是的。无需赘述,关键技术是在Post 模型上定义scope;像这样:

    class Post < ActiveRecord::Base
      scope :approved -> { where(status: Post.statuses['approved']) }
    end
    

    然后您可以通过Post.approved 仅显示已批准的帖子;或仅通过Post.where(user: foo).approved 为某个用户批准的帖子。

    为了显示标签列表,例如,您可以这样做:

    Post.where(user: foo).approved.map(&:tags).uniq
    

    这只会给您Array,而不是ActiveRecord::Collection。但这对于您的目的来说可能已经足够了。

    【讨论】:

    • 对,我应该更清楚一点——多个作者可以为一篇文章投稿。现在,posts-authors 和 posts-tags 连接表都是显式的,以便以后更容易添加标签排序、不同的作者信用等。获得一个 ActiveRecord::Collection 是理想的,因为作者的视图页面应该链接到标签;这可以通过自定义 SQL 完成,但我希望有一个更简单的解决方案。
    【解决方案2】:

    您可以限定has_many 本身。 例如。

    class Author
      has_many :moderated_posts, -> { moderated }, class_name: 'Post' 
    end
    
    class Post
      scope :moderated, -> { where(status: approved_statuses) }
    end
    

    【讨论】:

      猜你喜欢
      • 2015-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-21
      • 2017-10-09
      • 2014-04-24
      • 1970-01-01
      相关资源
      最近更新 更多