通过HABTM查询精确集

时间:2014-07-17 20:39:35

标签: sql ruby-on-rails ruby-on-rails-4 rails-activerecord has-and-belongs-to-many

在Rails 4中,我与has_and_belongs_to_manyCar之间存在一种Color关系。

给定一组colors我想找到那些颜色正好的车。我能得到的最接近的是:Car.joins(:colors).where('colors.id' => colors),但会返回任何颜色的所有Car

我想在ActiveRecord中完全这样做,因为两个表格都很大,所以像Car.joins(:colors).where('colors.id' => colors).to_a.select{|car| car.colors == colors}这样的东西不太理想。

知道怎么做到这一点吗?

1 个答案:

答案 0 :(得分:1)

我能够使用having和一些粗略的字符串插值SQL来获取它。我把它变成了你可以使用的范围:

# Car.with_exact(colors: colors)

class ActiveRecord::Base
  class << self
    def with_exact(associations={})
      scope = self
      associations.each do |association_name, set|
        association = reflect_on_association(association_name)
        scope = scope.joins(association_name)
          .group("#{table_name}.id")
          .having("COUNT(\"#{association.join_table}\".*) = ?", set.count)
          .having(%{
            COUNT(\"#{association.join_table}\".*) = SUM(
              CASE WHEN \"#{association.join_table}\".\"#{association.association_foreign_key}\"
              IN (#{set.to_a.map(&:quoted_id).join(', ')})
              THEN 1 ELSE 0 END
            )
          }.squish)
      end
      scope
    end
  end
end