2013-06-28 6 views
6

私は既存のRails 3.2アプリケーションを4.0にアップグレードしようとしています。私はレンガの壁にぶつかった。Rails 4 .order()がJOINSで字幕に変換される

私は3つのモデル、クライアント、サイト、および連絡先を持っています。サイトはクライアントに属する物理的な場所であり、クライアントは多数のサイトを持つことができます。連絡先は、1つ以上のサイトに所属する人物です。したがって、クライアントはサイトを通じて多くの連絡先を持つことができます。

クライアント:

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のです

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

問題があります:SE Client.find(1).contactsは、私がActiveRecord::StatementInvalid例外を取得私はORDER BY ... `contacts`.`name` ASCから来ている見当がつかない。 Contactsテーブルには名前の列はありませんが、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という名前の列が存在しないとSQLが文句を言いました。したがって、:through =>has_manyと使用すると、order句がマングルされるように見えます。

.order()を削除し、サイトモデルでdefault_scope -> { order(:name => :asc) }を使用しましたが、最初に報告されたのとまったく同じエラーが発生しました。あなたの二行目(Clientモデル)で右が、疲れている必要があり

答えて

9

解決策は単純です。 .order(:column_name => :asc)を使用する代わりに、.order('column_name ASC')に変更し、エラーがなくなり、予想される結果が得られました。私はもともと後者を持っていましたが、私のRails 3 - > 4アップグレードの一部として前者を実装していました。そしてRailsCastや他のドキュメントでそのようなコンベンションを見ました。

これは、.joins()を使用し、後で見つけたように結合テーブルの列で並べ替える場合にも必要です。アソシエーションも結合を使用するため、これは理にかなっています。

1

、あなたは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 ... ' –

関連する問題