Niewiele odkryłem, w jaki sposób można pisać zakresy powiązań polimorficznych w szynach, nie mówiąc już o tym, jak pisać zapytania na stowarzyszeniach polimorficznych.Zakresy i zapytania ze stowarzyszeniami polimorficznymi
W dokumentacji Railsa przyjrzałem się Polymorphic Associations section, Joining Tables section i Scopes section. Zrobiłem też mój uczciwy udział w wyszukiwaniu.
Weź tę konfigurację na przykład:
class Pet < ActiveRecord::Base
belongs_to :animal, polymorphic: true
end
class Dog < ActiveRecord::Base
has_many :pets, as: :animal
end
class Cat < ActiveRecord::Base
has_many :pets, as: :animal
end
class Bird < ActiveRecord::Base
has_many :pets, as: :animal
end
Więc Pet
może być animal_type
"Dog", "kot" lub "ptak".
Aby pokazać wszystkie struktury tabeli: tu jest mój schema.rb:
create_table "birds", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "cats", force: :cascade do |t|
t.integer "killed_mice"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "dogs", force: :cascade do |t|
t.boolean "sits"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "pets", force: :cascade do |t|
t.string "name"
t.integer "animal_id"
t.string "animal_type"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
Potem poszedł do przodu i kilka rekordów:
Dog.create(sits: false)
Dog.create(sits: true)
Dog.create(sits: true) #Dog record that will not be tied to a pet
Cat.create(killed_mice: 2)
Cat.create(killed_mice: 15)
Cat.create(killed_mice: 15) #Cat record that will not be tied to a pet
Bird.create
A potem poszedł i wykonane niektórzy pet
zapisy:
Pet.create(name: 'dog1', animal_id: 1, animal_type: "Dog")
Pet.create(name: 'dog2', animal_id: 2, animal_type: "Dog")
Pet.create(name: 'cat1', animal_id: 1, animal_type: "Cat")
Pet.create(name: 'cat2', animal_id: 2, animal_type: "Cat")
Pet.create(name: 'bird1', animal_id: 1, animal_type: "Bird")
A to jest konfiguracja! Teraz trudna część: chcę stworzyć kilka zakresów w modelu Pet
, które przekopują się w asocjacje polimorficzne.
Oto niektóre zakresy chciałbym napisać:
- Daj mi wszystko
Pets
z animal_type == „Dog”, który może siedzieć - Daj mi wszystko
Pets
z animal_type == „Cat” które zabiły co najmniej 10 myszy - Daj mi wszystkie
Pets
, które NIE są oba typu animal_type "Pies" i nie mogą siedzieć. (Innymi słowy: Daj mi wszystkie zwierzęta: wszystkie z nich z wyjątkiem psów, które nie mogą siedzieć)
więc moim Pet
modelu chciałbym umieścić moje zakresy tam:
class Pet < ActiveRecord::Base
belongs_to :animal, polymorphic: true
scope :sitting_dogs, -> {#query goes here}
scope :killer_cats, -> {#query goes here}
scope :remove_dogs_that_cannot_sit, -> {#query goes here} #only removes pet records of dogs that cannot sit. All other pet records are returned
end
Trudno jest napisać te zakresy.
Niektóre rzeczy, które znalazłem w Internecie, sprawiają wrażenie, że można pisać tylko te zakresy przy użyciu surowego kodu SQL. Zastanawiam się, czy możliwe jest użycie składni skrótu dla tych zakresów.
Wszelkie wskazówki/pomoc będą mile widziane!
'self.remove_dogs_that_cannot_sit' może być wykonane szybciej za pomocą include na' animal'. Wypróbuj 'all.includes (: animal) .reject {| pet | pet.animal_type == "Dog" &&! pet.animal.sits} ' – chrismanderson
zauważ, że jest subtelny, ale kiedy trafisz w część" .reject ", w rzeczywistości tracisz ruby i pozostawiasz SQL za sobą, stąd powolne. Możesz łączyć zakresy AREL i pozostać w SQL, np.by_dogs.where (sits: false) powinno być równoważne, zakładając, że nie masz wartości NULL i domyślnie ustawiony jest false w kolumnie boolowskiej w db. IIRC, może się mylę, kiedy schodzę ze szczytu mojej głowy, ale ".all" jest dorozumiany i niepotrzebny, gdy używasz łańcuchów AREL, o ile masz zasięg. – engineerDave