select * from users
join product_associations on product_associations.user_id = users.id
where product_associations.product_id in (2,3)
and not exists (
select *
from product_associations AS pa
where pa.user_id = users.id
and pa.product_id not in (2,3)
)
group by product_associations.user_id
having count(product_associations.product_id) = 2
It does two things, find users with: 1) all the product associations and 2) no other product associations.
Sqlfiddle example: http://sqlfiddle.com/#!2/aee8e/5
It can be Railsified™ (somewhat) in to:
User.joins(:product_associations)
.where(product_associations: { product_id: products })
.where("not exists (select *
from product_associations AS pa
where pa.user_id = users.id
and pa.product_id not in (?)
)", products.pluck(:id))
.group('product_associations.user_id')
.having('count(product_associations.product_id) = ?', products.count)