class Recipe < ActiveRecord::Base
has_many :ingredients
end
class Recipe::Ingredient < ActiveRecord::Base
belongs_to :product
# also has `require_in_filter` boolean attribute
end
I want get all recipes by products ids where all these products are in ingredients with require_in_filter = true. For example, a recipe has 2 ingredients: both with require_in_filter = true and they are referencing products with ids of 2 and 3.
- Query for recipes with products (2,3) MUST return this recipe.
- Query for recipes with products (2,3,17) MUST NOT return this recipe.
- Query for recipes with products (2) MUST NOT return this recipe.
What I tried so far:
Recipe.joins(:ingredients)
.where('recipe_ingredients.require_in_filter = ? AND recipe_ingredients.product_id IN (?)', true, [3,4])
.distinct
But this query returns recipes with ANY of the product ids (3 or 4 in this case). But I need only recipes with ALL of these products.
I found similar question PostgreSQL where all in array but doesn't help.
Recipe.joins(:ingredients)
.select('COUNT(*) AS count, recipes.*')
.where('recipe_ingredients.require_in_filter = ? AND recipe_ingredients.product_id IN (?)', true, [3,4])
.group('recipes.id').having('count(*) = ?', 2)
always return empty array
This raw sql
select recipes.*
from recipes
join recipe_ingredients
on recipe_ingredients.recipe_id = recipes.id
where not exists(
select * from recipe_ingredients ri
where ri.recipe_id = recipes.id
and ri.product_id not in(2,3,17)
)
and recipe_ingredients.require_in_filter = true
group by recipes.id
returns recipe with 2 and 3 as the only required products, but it shouldn't because 17 also must be required.
My SQL knowledge isn't sufficient to accomplish this task