::加载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 。 在CustomSerializerArticle模型中实现它的最佳方法是什么?

我的解决办法是:

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) 
+0

上你答案是正确的。但是现在我对我的代码有了新的要求。例如:在前3个地方应该是带有海报的文章,以及原来的顺序。在我的项目中调用模型方法也不总是可行的。在代码的某些部分,我已经有了文章列表,并且必须在那里对它们进行排序。不需要再次向DB发送请求。这就是为什么在这种情况下最好在'CustomSerializer'中排序。 – sig

+0

@sig在串行器中排序是一个相当不直观的黑客行为。但是,如果你只是在一个项目上工作,那并不重要。至少把你的代码改成'CustomSerializer.new(articles.includes(:poster))',这样你有时候避免N + 1 –

+0

当你在项目中工作不是孤单的,你必须牺牲直觉。因为有些东西不依赖于你。 – sig