Pracuję nad uaktualnieniem istniejącej aplikacji Rails 3.2 do wersji 4.0. Wpadłem jednak na ceglaną ścianę.Railsy 4 .order() zostają zmanipulowane przy pomocy JOINS
Mam trzy modele: klienta, witryny i kontaktu. Witryny to fizyczne lokalizacje należące do klienta, a klient może mieć wiele witryn. Kontakty to osoby należące do jednej lub wielu witryn. Tak więc klient może mieć wiele kontaktów za pośrednictwem witryn.
Klienci:
class Client < ActiveRecord::Base
has_many :sites, -> { where(:sites => {:deleted => false}).order(:name => :asc) }, :dependent => :destroy
has_many :contacts, -> { order(:lastname => :asc) }, :through => :sites
end
Strony:
class Site < ActiveRecord::Base
belongs_to :client
has_and_belongs_to_many :contacts
end
Kontakt:
class Contact < ActiveRecord::Base
has_and_belongs_to_many :sites
end
Problem polega na tym, że kiedy u se Client.find(1).contacts
, dostaję ActiveRecord::StatementInvalid
wyjątek:
Mysql2::Error: Unknown column 'contacts.name' in 'order clause': SELECT
contacts
.* FROMcontacts
INNER JOINcontacts_sites
ONcontacts
.id
=contacts_sites
.contact_id
INNER JOINsites
ONcontacts_sites
.site_id
=sites
.id
WHEREsites
.client_id
= 5 ANDsites
.deleted
= 0 ORDER BYcontacts
.lastname
ASC,contacts
.name
ASC
Jest problem: nie mam pojęcia, gdzie ORDER BY ... `contacts`.`name` ASC
pochodzi. Tabela kontaktów nie ma kolumny z nazwą, ale Rails próbuje ją posortować i nie wiem, skąd się bierze i jak ją usunąć. ORDER BY `contacts`.`lastname` ASC
jest łatwe; pochodzi z modelu klienta.
Te relacje działały bezbłędnie w wersji 3.2, ale teraz wyrzuć ten wyjątek w wersji 4.0.
UPDATE: To zostało podkreślone, że dodatkowy ORDER BY ... `contacts`.`name` ASC
pochodzi z pierwszej has_many
w modelu Klienci. Jednak intencją było uporządkowanie Stron, a nie Kontaktów. Próbowałem go zmienić na .order('sites.name' => :asc)
, a SQL skarżył się, że nie ma kolumny o nazwie sites.sites.name
. Wygląda więc na to, że przy korzystaniu z :through =>
z has_many
, klauzula zamówienia zostaje zmanipulowana.
Próbowałem usunąć .order()
i używając default_scope -> { order(:name => :asc) }
w modelu Witryny, ale dostałem dokładnie ten sam błąd, co pierwotnie zgłoszono.
Nie OP, ale założyłem, że kolejność odnosi się do tabeli stron, która miałaby kolumnę nazwy (ale nie kolumnę nazwiska). –
Święta krowa, masz rację. Wyjąłem '.order()', a zapytanie zadziałało. Ale intencją było uporządkowanie Stron, a nie Kontaktów, jak słusznie ocenił Eric. Jako test zmieniłem go na '.order ('sites.name' =>: asc) 'i został zgłoszony nowy wyjątek, narzekając, że" sites.sites.name "nie istnieje. Tak więc, tak czy inaczej, łamane jest '.order()'. –
Dziwne, masz rację. @EricPalace, założyłem * z serca *, że chodziło o 'Klienta'. Ostatnim razem, gdy musiałem zamówić podobną listę, w końcu użyłem ': conditions => [" joined_table.some_column ... "z tego powodu –