两个 has_many 关联到同一模型

Two has_many associations to the same model

我有一个包含很多帖子的博客模型,其中一些帖子是热门帖子。我的意图是有类似下面的东西。

class Blog
  has_many :posts
  has_many :top_posts, class_name: 'Post'
end

class Post
  belongs_to :blog
end

可以看到,posts和top posts是同一个对象,但是top posts的集合和posts的集合是不同的。有些帖子也是热门帖子,但有些则不是。

问题是当我尝试执行 blog.top_posts 时,它 return 与 blog.posts 是同一个集合,它们都是来自该博客的帖子。我希望 blog.top_posts 到 return 只有我通过 blog.top_post_ids << random_post 关联为博客热门帖子的帖子。提前致谢!

我假设,就像大卫在评论中问你的那样,你有特定的 post。

并且 post 可能会变成 top_post,例如,如果他有 50 个赞,或 1000 次浏览,或者在您的数据库中持久存在的任何属性使 post 变成顶部 post 。

如果您的数据库中没有任何标准,则不能使用活动记录来获取 top_post。 无论如何,如果你有,你应该使用范围:

 class Blog
  has_many :posts

 end

class Post
  belongs_to :blog
  scope :top_posts, -> { where(views > 1000 ) }  #or any conditions base on your criterias
end

而且你可以简单地得到它们:

    blog = Blog.first
    blog.posts.top_posts # => [top posts belonging to this blog]

这是一个基于假设的答案...

范围文档:http://guides.rubyonrails.org/active_record_querying.html#scopes 小号

使用 has_many 的问题在于它只是将 Blog 对象的 ID 附加到每个 Post 对象,因此当您调用 blog.postsblog.top_posts 它执行一个 SQL 查询寻找 Posts WITH id=Blog.id 因此,你得到相同的列表两次。

我建议你有一个 has_many posts,然后对每个 post 和 "Top Post." 返回的列表进行排序,或者,如果你想避免排序我建议这样:

class Blog
  has_many :posts

  def initialize
    @top_posts = []
  end

  def add_top_post(post)
    if self.posts.include?(post)
      @top_posts << post
    end
  end
end

class Post
  belongs_to :blog
end

范围如何? http://guides.rubyonrails.org/active_record_querying.html#scopes

    class 博客
      has_many:帖子
    结尾

    class Post
      belongs_to:博客
      范围:顶部,-> {其中top_post:真}
    结尾

    # 这会得到所有的热门帖子
    blog.posts.top