如何在ActiveRecord的查询

问题描述:

使用AND条件我现在有这三个表:如何在ActiveRecord的查询

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 

我尝试这样做,将返回所有包含所有的成分在我的搜索鸡尾酒SEACH。 到目前为止,我已经设法想出这个:

CocktailIngredient.where(ingredient_id:[1,4])的地图。(&:鸡尾酒).uniq

它返回所有包括鸡尾酒1或4的ingredient_id。我试图只返回含有两种成分的鸡尾酒,编号为1和4.

任何帮助将不胜感激。

+0

当我研究你的问题...在鸡尾酒表中字段'ingridients'的目标是什么? – AntonTkachov

+0

为了方便地在鸡尾酒会上向用户展示原料 – pfrasdog

这里是一个广义的版本,如果你有一个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

+0

我认为这样的链接总是会导致空白排列,因为这种条件相互矛盾。 – AntonTkachov

+0

是的,它在使用.where链时返回一个空数组 – pfrasdog

+0

没错,我编辑了我的答案! –

我发现现在最好的是:

Cocktail.joins(:cocktail_ingredients).where(cocktail_ingredients: { ingredient_id: 1, cocktail_id: CocktailIngredient.where(ingredient_id: 4).select(:cocktail_id) })

我不认为这是我们可以做的最好,但它更优化,然后解决方案