2016-05-12 10 views
0

Also ich baue eine Benutzeroberfläche, um einen Benutzer einen Zoo für Tier und/oder von Trainer für eine Rails 4 Anwendung mit Postgres finden zu lassen.Gibt es eine bessere Möglichkeit, diese ActiveRecord Rails 4.2-Abfrage mithilfe von Bereichen zu schreiben?

Es gibt eine Reihe von Tier-Checkboxen und eine Reihe von Trainer-Checkboxen. Ein Benutzer kann mehrere Kontrollkästchen sowohl im Trainer- als auch im Tierbereich aktivieren.

hier die Schienen Code ich die Abfrage in der Konsole

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 

Dies führt zu 4 SQL-Abfragen erstellen verwenden. Gibt es eine effizientere Möglichkeit, dies zu schreiben? Sollte ich rohe SQL mit einer ODER-Bedingung verwenden?

Modell Setup

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 

Antwort

0

Ja, können Sie die where Klausel selbst festlegen:

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

Sie einen Bereich zoo finden definieren:

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 

Dann nutzen es:

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

Btw, wird diese erzeugt nur eine einzelne Abfrage, da wir joins in der obigen Abfrage verwenden

Verwandte Themen