2017-10-13 104 views
1

使用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

回答

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

+0

我認爲這樣的鏈接總是會導致空白排列,因爲這種條件相互矛盾。 – AntonTkachov

+0

是的,它在使用.where鏈時返回一個空數組 – pfrasdog

+0

沒錯,我編輯了我的答案! –

1

我發現現在最好的是:

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

我不認爲這是我們可以做的最好,但它更優化,然後解決方案