使用ActiveRecord QueryMethods#from从现有Relation构建新范围

时间:2017-06-29 14:19:23

标签: ruby-on-rails activerecord

Active Record Query Interface上的Rails文档从未如此详尽,API doc也没有多大帮助,所以我从未使用过 QueryMethods# 直到我发现任何现有的ActiveRecord Relation都可以用作子查询。

例如,如果你有

@results= Paper\
  .select( :color, :box_id, 'MAX(size) AS maximum_size' )\
  .group( :color, :box_id )\
  .having( 'AVG(size) > 123' )

您可以将此Relation重用为新查询的中间结果表:

Box.from(@results,:previous_scope)\
  .select( :box_id, 'previous_scope.color AS wrap_color')\
  .joins( 'LEFT JOIN items USING (box_id)' )\
  .where( items: {color:'red'} )

这太棒了,让我免于编写令人讨厌的find_by_sql语句来构建复杂的查询。

当然,最好定义一些不错的范围来整理代码并避免重复:

class Box < ActiveRecord::Base

  scope :suitable_colors, ->(this,color) {
    from(this,:previous_scope)\
    .select( :box_id, 'previous_scope.color AS wrap_color')\
    .joins( 'LEFT JOIN items USING (box_id)' )\
    .where( items: {color:color} )
  }

end

到目前为止一切顺利,如果像Box.suitable_colors(@results,'green')一样使用,这将有效。

但是避免将Relation作为参数传递会更好,所以可以像@results.suitable_colors('green')一样链接它。我使用from(self,:previous_scope)天真地尝试了不同的方法,但没有成功(最后得到RuntimeError: unsupported: ClassArgumentError: A copy of Box has been removed from the module tree but is still active!)。

问题是@results.is_a? ActiveRecord::Relation而不是@results.is_a? Box。是否可以将suitable_colors定义为Box类中的作用域?

0 个答案:

没有答案