A way to optimize the time and readability of a programmer, in my opinion:
candidate_users = User.all(:include => :items)
candidate_users.reject! do |candidate|
candidate.items.map {|item| item.color}.sort != ['black', 'red']
end
If you expect to go through metric user loading there, you will need a SQL server. Warning: SQL is not my bag, child: test before use.
select users.*, items.* FROM users
INNER JOIN items_users ON (items_users.user_id = users.id)
INNER JOIN items ON (items_users.item_id = items.id)
GROUP BY users.id HAVING COUNT(DISTINCT items.color) = 2
What I think is an evil mess:
1) captures every combination of users / items 2) Winnows down for users who have items in exactly 2 different colors
This means that you need to:
candidate_users.reject! do |candidate|
candidate.items.map {|item| item.color}.sort != ['black', 'red']
end
You can probably completely eliminate the need for ruby, but SQL will get seven ugly flavors. (The cross unites, oh my ...)
source
share