2017-03-26 8 views
1

私は最適化しようとしているjankyクエリがあります。私はいくつかのメンバーシップパケットロジックに基づいてユーザーレコードのアクティブレコード結合を返したいと思います。select文にif/elseロジックがあるときにActiveRecordクエリを最適化する

ids = User.joins(:memberships).includes(:memberships).select do |user| 
    if user.memberships.count <= 1 
    user.membership_packet_sent_at.blank? 
    else 
    user.membership_packet_sent_at.blank? && user.current_membership.created_more_than_30_days_ago? 
    end 
end.uniq.map(&:id) 

User.where(id: ids) 

私は上記に実行している問題は、私はアクティブなレコード協会の代わりに、配列を返すために選択し使用する方法がわからないので、私は2つのクエリをしなければならないということです。

  1. selectからactiverecordの関連付けを返すにはどうすればよいですか?
  2. 選択ブロック内でロジックを整理するためのより良い方法はありますか?

編集:

いくつかのリファクタリングの後、私はメソッドに選択ロジックの一部を移動することができました:

`` `

ids = User.joins(:memberships) 
      .where(membership_packet_sent_at: nil) 
      .select(&:current_membership_packet_expired?) 
      .uniq 
      .map(&:id) 

User.where(id: ids) 

` ``

代わりにactiverecordアソシエーションを返す方法の問題に取り組んでいます

+0

これは非常にジャッキーだと言っても過言ではありません。主な最適化エラーの初心者は通常N + 1(反復の中のクエリ)です。これは 'preload'を介して防ぐことができます。 –

+0

@maxple fair point。選択してエイジスのソリューションを読む際にメソッドをクリーンアップした後、それは意味をなさない。ありがとう。 – Huy

答えて

1

selectを適用した後、現在Relationオブジェクトを直接返すことはできません。 RelationオブジェクトはちょうどSQLビルダーであるとselect方法は、そのカスタムプロセスを実行することができます実際のデータ

  • では動作しません

    • これらは私が考える可能性が主な理由ですそれはwhere

    のような別のクエリでチェーンにselectの結果ことはできませんので、有効なSQLクエリとして表現することができません3210は同様の考え方を述べている。

  • 関連する問題