2016-10-19 5 views
1

に含まれての結果を注文しようとすると、偉大行くことは、私は別のモデルに接合されているActiveRecordのモデルを複数回持っているのActiveRecord

claims = Claim.all.includes(:user, :treated_by, :person_involved) 

を今私は(それらがメモリにせずに)主張をソートしたいので、私のような何かをしたい:私は使用してN + 1つのクエリを避ける含ま

Claim.all.includes(:user, :person_involved, :treated_by).order('treated_by.last_name') 

しかし、私はこのように私のユーザーしない限り、テーブル名を無効なSQLを取得する:はっきりユーザーのサブセットで治療することによって順序は、例えばLAST_NAME私を助けにはなりません

Claim.all.includes(:user, :person_involved, :treated_by).order('users.last_name') 

。これを正しく行うにはどうしたらいいですか?

答えて

1

his answerで述べたAbishek Kumarとして、あなたはおそらくべきincludesは、includesの代わりにjoinsを使用してくださいN + 1のクエリの問題を防ぐためにそこに。 も同様に関連付けで並べ替えることができますが、あなたの関連付けにカスタム名がある場合は役に立ちません。

私はあなたがしばらくのActiveRecordの素敵で居心地の良い場所の外で少しステップ、および手動結合文を記述する必要がありますと思う:

Claim.all 
    .joins("INNER JOIN users AS treated_bys ON claims.treated_by_id = treated_bys.id") 
    .order("treated_bys.last_name ASC") 

...あなたはincludesでクエリをspinkleすることができますN + 1個のクエリなどを避けるために必要ならば

+1

いい回答です! 'INNER JOIN users AS treated_bys ON ... 'は、' processed_by'関連値を持つものだけ 'claim'コレクションを制限することに言及したいと思います。 'processed_by'を伴わないクレームは、データベースからフェッチされません。代わりにLEFT JOINを使用する方が安全かもしれません。 http://www.w3schools.com/sql/sql_join_left.asp – Semjon

+0

その説明をありがとうございます@セジョン – Frost

0

ここで、クエリのテーブル名は複数でなければなりません。 次で試してみてください。

Claim.all.includes(:user, :person_involved, treated_by).order('treated_bys.last_name') 

コーディングハッピー!

+0

申し訳ありませんShefaleeですが、usersテーブルを使用するモデルユーザーが1人しかないため、processed_bysテーブルはありません。私は、treat_by結合を介してドラッグされたユーザーのサブセットに対してorder by節をスコープする必要があります。 – robertpostill

+0

だから、ここでは、processed_byはテーブルではありません。それで治療されたのは? @robertpostill – user100693

+0

Shefalee、processed_byは、Claimのbelongs_to関係です(質問の先頭近くのクラス定義に従って)。ユーザーテーブル(他のユーザーテーブルと同様)を指しているので、ユーザーにとって効果的です。 – robertpostill

0
Claim.all.includes(:user, :person_involved, treated_by).sort_by { |c| c.treated_by.last_name } 
+0

Dinesh、これは結果セットのメモリ内ソートになります。私はDBに送られたクエリを変更するものを期待していたので、ページを設定したり、さらにスコープを変更することができました。 – robertpostill

+0

@robertpostillはい、メモリソートです。 – dnsh

+0

@robertpostill 'Claim.joins(:treated_by).order( 'users.last_name')。includes(:user、:person_involved)'を試すことができます。あなたはprocessed_byユーザーを事前にロードすることはできませんが、私はあなたがレコードを注文することができると思います。 – dnsh

0

編集:これは機能しません。これを試してはいけません。

これは機能しますか?

Claim.all 
    .includes(:user, :person_involved, :treated_by) 
    .order(treated_by: { last_name: :asc}) 

私はActiveRecordのは、参加するためにその構文を受け入れます知っているが、それは、ソートのために働く場合、私はわかりませんよ。


更新:ActiveRecordは、レコードの注文にこの構文をサポートしていません。 orderメソッドは、文字列またはハッシュのいずれかを受け入れます。ハッシュを取得すると、キーは列であり、値は:asc, :desc; :ASC, :DESC、 "asc"、 "desc"、 "ASC"、 "DESC" ). It seems like it does not support nested hashes, like it does in where`のいずれかになります。ここ

1

includesは別々のクエリを使用して関係をプリロードし、したがって、他のテーブルの列に応じてそれを注文することはできません。

あなたが代わりにjoinsを使用する必要があります。

+0

はい、これは正しいですが、 'includes'の代わりに' joins'を使うだけでは、ソートのための特定の関連付けを参照する必要はありません。私は、このアプローチは手動で結合を書くことと組み合わせなければならないと考えています。 – Frost

+0

手動で参加を書く必要はありません。どのバージョンのレイルですか? –

+1

元の質問に重要な点がないと思います。つまり、OPは、関連するテーブル名と同じテーブル名を持たない特定のアソシエーションの列をソートする方法を求めています。ユーザーモデル。したがって、 'users.last_name'による注文だけでは不十分です。 – Frost

関連する問題