::加载ActiveModel串行排序并序列
问题描述:
例如我有两个型号的ActiveRecord:::加载ActiveModel串行排序并序列
class Article < ActiveRecord::Base
has_one :article_poster
end
和
class ArticlePoster < ActiveRecord::Base
belongs_to :article
end
在某些控制器:
CustomSerializer.new(articles)
CustomSerializer:
class CustomSerializer < ActiveModel::Serializer
end
我有4篇文章,有海报,没有它。 例如:
1日文章海报目前
第二条海报不存在
3日文章海报目前
第四条本海报
我通过海报的存在需要为了文章:1,3,4,2 。 在CustomSerializer
或Article
模型中实现它的最佳方法是什么?
答
我的解决办法是:
class CustomSerializer < ActiveModel::Serializer
def initialize(resources, options = {})
resources = sort(resources)
super(resources, options)
end
def sort(resources)
top = []
regular = []
resources.each do |article|
if article.poster
top << article
else
regular << article
end
end
resources = top + regular
end
end
答
下面是使用SQL
class Article < ActiveRecord::Base
has_one :article_poster
scope :join_article_posters, -> {
joins('LEFT OUTER JOIN article_posters ON article_posters.article_id = article.id') }
}
scope :posters_first -> { join_article_posters.order(article_posters: { id: :desc }) }
end
posters_first的解决方案可以更好地做不同取决于你的数据库
CustomSerializer.new(articles.posters_first)
上你答案是正确的。但是现在我对我的代码有了新的要求。例如:在前3个地方应该是带有海报的文章,以及原来的顺序。在我的项目中调用模型方法也不总是可行的。在代码的某些部分,我已经有了文章列表,并且必须在那里对它们进行排序。不需要再次向DB发送请求。这就是为什么在这种情况下最好在'CustomSerializer'中排序。 – sig
@sig在串行器中排序是一个相当不直观的黑客行为。但是,如果你只是在一个项目上工作,那并不重要。至少把你的代码改成'CustomSerializer.new(articles.includes(:poster))',这样你有时候避免N + 1 –
当你在项目中工作不是孤单的,你必须牺牲直觉。因为有些东西不依赖于你。 – sig