2017-08-16 15 views
2

のJOIN INNERとeager_load、私たちは大きなActiveRecord::Relationを生成するコードの一部を持っていることに気付きました。これは、このような.joins()呼び出し、何かにカスタムSQLスニペットを使用しています。RailsのActiveRecordのが大のRailsアプリで

def foos 
    Foo. 
    joins("INNER JOIN bars ON foos.bar_id = bars.id"). 
    joins("INNER JOIN baz ON bars.baz_id = baz.id"). 
    where(<some condition on bars>) 
end 

(この例のようにJOIN sがより複雑であることに注意してください、そうでない場合、私は明らかにちょうどFoo.joins(bar: :baz)にしてください。)さて、いくつかにActiveRecord::Relationが使用されている場所のうち、それは問題ありません。しかし、他のものでは、結果セットにbarsの関連付けをeager-loadedしたいと考えています。

すると、このような何かをする方法はあります:

def scope_with_bars_eager_loaded 
    foos.eager_load(:bars, using_existing_join_in_query: true) 
end 

私が思い付くことができます最も近いものがある:多くのより複雑であり、またない

def array_with_bars_eager_loaded 
    foos.pluck(<fields we need>).map do |fields| 
    bar = Bar.new(<get bar data from fields>) 

    # This of course doesn't behave as well as a Foo 
    # that we've loaded normally in regards to callbacks, 
    # fields we didn't SELECT, etc. But it's probably 
    # fine enough for this use-case (we're using this 
    # data to render a page). 
    Foo.new(<get foo data from fields>, bar: bar) 
    end 
end 

私たちにはActiveRecord::Relationのメリットを与えてください。ここのお手伝いをいただければ幸いです!

-

注:

『1つのクエリでの負荷、データベース内のすべての列、時には複数回』のRailsのデフォルトの動作を回避するための任意の提案、特に私が代わりに.pluckを使用理由です(感謝しています.selectは、明示的ではないにそれを教えても、Fooですべてをロードするクエリを構築するよう.select、)の。例:Foo.includes(:bar).where(bars: { condition: true }).select(:id)foosのすべての列を選択し、二回foos.id選択します。

+0

私はあなたがそれを使用している方法に多少依存します。 'Foo.new(hash_of_stuff_i_plucked_from_the_db)'を実行すると、レコードは新しいレコードのように動作し、DBからフェッチされません。これは、コールバックになると予期しない動作が発生し、たとえばフォームに渡すとどうなりますか。 – max

+0

'.joins'が' LEFT INNER JOIN'を作成しているので 'joins(" INNER JOIN bar foos.bar_id = bars.id ")'というコードはちょっと変わっています。 :バー) '。 '.joins'と' .eager_load'の主な違いは '.joins'は' INNER'と '.eager_load''OUTER'を使います。また – max

+0

.pluck'セレクトリターン(アレイの)配列を返し.pluck' 'のActiveRecord :: Relation'と'ことである.select'と ''の差。あなたは '.select'を使って、ARにぴったりな列を正確に伝えることができます。 '@foo = Foo.select( 'foos.id、foos.baz、bars.id、bars.baz').joins(:bars)'は、例えば、指定された列だけをロードします。 – max

答えて

0

私はfoosメソッドを再構築して、単にincludesを実行できるようにしました。それでもSELECT EDいるすべてのフィールドを持つスーパー満足していないが、私はそれはあなたがActiveRecord代わりのSequelのようなものを使用するために得るものだと思います。

関連する問題