我目前有这三个表:
create_table "cocktail_ingredients", force: :cascade do |t|
t.integer "cocktail_id"
t.integer "ingredient_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["cocktail_id"], name: "index_cocktail_ingredients_on_cocktail_id"
t.index ["ingredient_id"], name: "index_cocktail_ingredients_on_ingredient_id"
create_table "cocktails", force: :cascade do |t|
t.string "title"
t.string "ingredients"
t.text "method"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
create_table "ingredients", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
我正在努力做一个能够回收所有包含我搜索中所有成分的鸡尾酒的搜索。 到目前为止,我已经设法提出这个:
CocktailIngredient.where(ingredient_id:[1,4])。map(&amp ;: cocktail).uniq
返回包含1或4的ingredient_id的所有鸡尾酒。我正在尝试仅返回含有ID为1和4的两种成分的鸡尾酒。
非常感谢任何帮助。
答案 0 :(得分:1)
如果你有ingredient_ids
数组,那么这是一个通用版本:
cocktail_ingredients = [1, 4]
cocktail_ingredients = CocktailIngredient.where(ingredient_id: ingredient_ids).select(:cocktail_id)
cocktail_ingredients = cocktail_ingredients.group(:cocktail_id).having('COUNT(ingredient_id) >= ?', ingredient_ids.count)
cocktails = Cocktail.where(id: cocktail_ingredients.select(:cocktail_id))
以下是Cocktail
模型的测试范围(使用Rspec和FactoryGirl)。您只需致电Cocktail.with_ingredients([1,4])
。
在cocktail.rb中:
scope :with_ingredients, (lambda do |ingredient_ids|
cocktail_ingredients = CocktailIngredient.where(ingredient_id: ingredient_ids).select(:cocktail_id)
cocktail_ingredients = cocktail_ingredients.group(:cocktail_id).having('COUNT(ingredient_id) >= ?', ingredient_ids.count)
where(id: cocktail_ingredients.select(:cocktail_id))
end)
和cocktail_spec.rb:https://gist.github.com/ArnoHolo/54b9259fbaa067d7abbf04a73d94ec40
答案 1 :(得分:1)
我现在发现的最好的是:
Cocktail.joins(:cocktail_ingredients).where(cocktail_ingredients: { ingredient_id: 1, cocktail_id: CocktailIngredient.where(ingredient_id: 4).select(:cocktail_id) })
我认为这不是我们能做的最好的事情,但它比以前的解决方案更优化了