Rails 包含范围
Posted
技术标签:
【中文标题】Rails 包含范围【英文标题】:Rails includes with scope 【发布时间】:2014-11-27 08:47:06 【问题描述】:我有一个名为 Author 的模型。一个作者有很多文章。 文章有一个名为 .published 的范围,它执行:where(published: true)。
我想加载作者,以及已发表的文章。 我试过了:
Author.includes(:articles.published).find(params[:author_id])
但这会引发错误:未定义的方法“已发布”。 有什么想法吗?
【问题讨论】:
是的,这只是需要用一些不同的术语来搜索。这是“急切加载作用域关联”,请参阅:***.com/questions/7937759/… ...结果是重复的? 【参考方案1】:我认为最好的解决方案是:
Author.includes(:articles).where(:articles=>published: true).find(params[:author_id])
或者你可以创建范围:
class Author < ActiveRecord::Base
scope :with_published_articles, -> includes(:articles).where(articles: published: true)
end
然后:
Author.with_published_articles.find(params[:author_id].to_s)
【讨论】:
【参考方案2】:我会在 Author
上指定一个名为 with_published_articles
的范围,如下所示:
scope :with_published_articles, -> joins(:articles).merge(Article.published)
这将解决您的问题,同时在您的 Author
模型上指定 where(active: true)
,以防 published
和 Article
的行为将来发生变化。
所以现在你可以调用:
Author.with_published_articles.find(params[:author_id])
【讨论】:
这是最好的答案,因为它没有将作者与文章的“已发布”含义的内部实现结合起来 据我所知joins不会急于加载,所以这仍然会有n+1的问题 这是正确的答案,因为它降低了未来的更改成本(避免代码重复和泄露已发表文章概念的实现细节)。正如 tantrix 所说,它还避免了作者和文章的进一步耦合。【参考方案3】:试试这个代码:
Author
.includes(:articles).where(published: true).references(:articles)
.find(params[:author_id])
您可以在此处找到有关上述示例的更多信息: includes api doc
【讨论】:
【参考方案4】:使用:
class Articles < ActiveRecord::Base
scope :published, -> where(articles: published: true)
end
在 Autor 上定义范围
class Author < ActiveRecord::Base
scope :with_published_articles, -> joins(:articles).merge(Articles.published)
end
或者
Author.joins(:articles).merge(Articles.published).find(params[:author_id])
【讨论】:
以上是关于Rails 包含范围的主要内容,如果未能解决你的问题,请参考以下文章