Reputation: 8318
A given Car
has many features
which are connected through listed_features
. How can I find all cars
which have the features
with the ids
1
AND 2
AND 3
? The cars
can have more features
but they have to have the first three features
.
The setup:
rails g model Car name:string
rails g model Feature name:string
rails g model ListedFeature car:references feature:references
app/models/car.rb
class Car < ActiveRecord::Base
has_many :listed_features
has_many :features, through: :listed_features
end
app/models/listed_features.rb
class ListedFeature < ActiveRecord::Base
belongs_to :car
belongs_to :feature
end
app/models/features.rb
class Feature < ActiveRecord::Base
end
Upvotes: 2
Views: 67
Reputation: 52336
The trick here may be to state that you need to get three matches from the features table.
id_list = [1, 2, 3]
Car.joins(:features).
where(features: { id: id_list }).
references(:features).
group(:id).
having("count(*) = ?", id_list.size)
Another approach would be to have a scope on Car for has_feature:
def self.has_feature(feature_id)
where(CarFeature.where("car_features.car_id = cars.id and car_features.feature_id = ?", feature_id).exists)
end
You can then:
Car.has_feature(1).has_feature(2).has_feature(3)
... or make it more elegant with another class method that accepts an array of features and then applies the has_feature scope multiple times for you.
It would generate very efficient SQL.
Upvotes: 3