2013-06-28 46 views
6

我正在將現有的Rails 3.2應用程序升級到4.0。不過,我碰到了一堵磚牆。Rails 4.order()得到連接JOINS

我有三種模式,客戶端,站點和聯繫人。站點是屬於客戶端的物理位置,客戶端可以有多個站點。聯繫人是屬於一個或多個網站的人員。因此,客戶可以通過網站獲得許多聯繫。

客戶:

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 

網站:

class Site < ActiveRecord::Base 

    belongs_to :client 
    has_and_belongs_to_many :contacts 

end 

聯繫人:

class Contact < ActiveRecord::Base 

    has_and_belongs_to_many :sites 

end 

的問題是,當I U SE Client.find(1).contacts,我得到一個ActiveRecord::StatementInvalid例外:

Mysql2::Error: Unknown column 'contacts.name' in 'order clause': SELECT contacts .* FROM contacts INNER JOIN contacts_sites ON contacts . id = contacts_sites . contact_id INNER JOIN sites ON contacts_sites . site_id = sites . id WHERE sites . client_id = 5 AND sites . deleted = 0 ORDER BY contacts . lastname ASC, contacts . name ASC

有問題:我不知道那裏的ORDER BY ... `contacts`.`name` ASC的來源。聯繫人表沒有名稱列,但Rails正在嘗試對其進行排序,我不知道它來自哪裏或如何刪除它。 ORDER BY `contacts`.`lastname` ASC很容易;它來自客戶端模型。

這些關係在3.2中完美無缺地工作,但現在在4.0中拋出這個異常。

UPDATE: 它已經指出,額外的ORDER BY ... `contacts`.`name` ASC從在客戶機模型中的第一has_many到來。然而,其意圖是對網站進行分類,而不是聯繫人。我試圖將其更改爲.order('sites.name' => :asc),SQL抱怨沒有名爲sites.sites.name的列。因此,看起來在使用:through =>has_many時,訂單子句會受到損壞。

我試着在Sites模型中刪除.order()並使用default_scope -> { order(:name => :asc) },但得到的錯誤與原來的報告完全相同。

回答

9

解決方法很簡單。我沒有使用.order(:column_name => :asc),而是將其更改爲.order('column_name ASC'),並且錯誤消失,產生了預期結果。我原來是後者,但是在我的Rails 3 - > 4升級中實現了前者,並在RailsCasts和其他文檔中看到了這樣的約定。

這在使用.joins()時也是必要的,並且通過連接表列進行排序,正如我後來發現的那樣。這是有道理的,因爲該關聯也使用連接。

1

你一定累了,就在那裏你的第二個行(Client模型),你有order(:name=> :asc),它應該是:

class Client < ActiveRecord::Base 

    has_many :sites, -> { where(:sites => {:deleted => false}).order(:lastname => :asc) }, :dependent => :destroy 
    has_many :contacts, -> { order(:lastname => :asc) }, :through => :sites 

end 
+0

不是OP,但我認爲順序是指網站表,它將有一個名稱列(但不是姓氏列)。 –

+0

聖牛,你說得對。我拿出'.order()',並且查詢工作。但是,其目的是對網站進行排序,而不是按照Eric的正確評估。作爲一項測試,我將它改爲'。order('sites.name'=>:asc)'並拋出一個新的異常,抱怨'sites.sites.name'不存在。所以無論如何,'.order()'在這裏被打破了。 –

+0

奇怪的是,你是對的@EricPalace,我假設*來自心臟*,它指的是'客戶端'。上次我不得不訂購一個類似的列表,我最終使用':conditions => [「joined_table.some_column ...'出於這個原因 –