2016-05-12 59 views
0

因此,我正在構建一個UI,以便讓用戶通過動物和/或培訓師找到一個動物園,並使用postgres爲Rails 4應用程序提供支持。有沒有更好的方式來使用範圍來編寫這個ActiveRecord Rails 4.2查詢?

有一系列動物複選框和一系列教練複選框。用戶可以在教練和動物部分中檢查多個複選框。

這裏是我用來構建查詢

animal_ids = [1, 2, 3] 
trainer_ids = [1, 2] 

# OR query - either an animal or trainer can be present to find a zoo 
a = Zoo.includes(:animals).where(animals: { id: animal_ids}) 
b = Zoo.includes(:trainers).where(trainers: { id: trainer_ids}) 
zoos = a+b 

這導致在控制檯4個SQL查詢Rails代碼。有沒有更有效的方法來寫這個?我應該使用OR條件的原始sql嗎?

模型建立

class Zoo < ActiveRecord::Base 
    has_many :animals, through: zoo_animals 
    has_many :trainers, through: zoo_trainers 
    has_many :zoo_trainers 
    has_many :zoo_animals 
end 

class Animal < ActiveRecord::Base 
    has_many :zoos, through :zoo_animals 
    has_many :zoo_animals 
end 

class Trainer < ActiveRecord::Base 
    has_many :zoos, through :zoo_trainers 
    has_many :zoo_trainers 
end 

class ZooAnimal < ActiveRecord::Base 
    belongs_to :animal 
    belongs_to :zoo 
end 

class ZooTrainer < ActiveRecord::Base 
    belongs_to :zoo 
    belongs_to :trainer 
end 

回答

0

是的,你可以自己指定where條款:

Zoo.includes(:animals, :trainers).references(:animals, :trainers).where("animals.id IN (?) OR trainers.id IN (?)", animal_ids, trainer_ids) 
0

您可以定義範圍,找到zoo

class Zoo < ActiveRecord::Base 
    scope :from_animal_and_trainer, -> (animal_ids, trainer_ids) { 
    joins(:animals, :trainers).where(Animal.arel_table[:id].in(animal_ids) 
             .or(Trainer.arel_table[:id].in(trainer_ids))) 
    } 
end 

然後使用它:

animal_ids = [1, 2, 3] 
trainer_ids = [1, 2] 
zoos = Zoo.from_animal_and_trainer(animal_ids, trainer_ids) 

順便說一句,這將產生只是一個單一的查詢,因爲我們在上面的查詢使用joins

相關問題