通过关联订购 has_many

Ordering a has_many through association

我想急切地加载一个 ActiveRecord 集合及其关联的集合:

class BodyPort < ActiveRecord::Base
  has_many :body_port_dimensions
  has_many :dimensions, through: :body_port_dimensions, order: 'dimensions.value'
  scope :ordered, order('name ASC')
end 
class BodyPortDimension < ActiveRecord::Base
  belongs_to :dimension
end
class Dimension < ActiveRecord::Base
end

急切加载协会:

BodyPort.includes(:dimensions).ordered

生成 SQL:

SELECT `body_ports`.* 
  FROM `body_ports` 
  ORDER BY name ASC
SELECT `body_port_dimensions`.* 
  FROM `body_port_dimensions` 
  WHERE `body_port_dimensions`.`body_port_id` IN (3, 5, 7, 6, 2, 8, 9, 4, 1) 
  ORDER BY dimensions.value

引发 SQL 异常:

=> ActiveRecord::StatementInvalid: Mysql2::Error: 
   Unknown column 'dimensions.value' in 'order clause': 
   SELECT `body_port_dimensions`.* 
     FROM `body_port_dimensions` 
     WHERE `body_port_dimensions`.`body_port_id` IN (3, 5, 7, 6, 2, 8, 9, 4, 1) 
     ORDER BY dimensions.value 

如何生成内部联接 SQL 改为:

SELECT `dimensions`.* 
  FROM `dimensions` 
  INNER JOIN `body_port_dimensions` 
    ON `dimensions`.`id` = `body_port_dimensions`.`dimension_id` 
  WHERE `body_port_dimensions`.`body_port_id` IN (3, 5, 7, 6, 2, 8, 9, 4, 1) 
  ORDER BY dimensions.value

edsinclair patch 之后:

config/initializers/extensions.rb:

require "active_record_has_many_through_patch"

lib/active_record_has_many_through_patch.rb:

module ActiveRecordHasManyThroughPatch
  def self.through_options
    through_options = {}

    if options[:source_type]
      through_options[:conditions] = { reflection.foreign_type => options[:source_type] }
    else
      if options[:conditions]
        through_options[:include]    = options[:include] || options[:source]
        through_options[:conditions] = options[:conditions]
      end

      if options.has_key?(:order)
        through_options[:order] = options[:order]
        if options.has_key?(:through) && options.has_key?(:source)
          through_options[:include] = options[:source]
        end
      end
    end 

    through_options
  end
end