2016-10-30 19 views
0

私は(天気予報局)と観測点を持つRailsアプリケーションを持っています。このアプリは現在の風速と方向で地図上に多くの気象観測所を表示します。Rails eager_load関連の条件付き

私はステーションを選択し、ステーションごとに最新の観測を結合する方法で使用される方法を持っています。

class Station < ActiveRecord::Base 
    has_many :observations 
    def self.with_observations(limit = 1) 
    eager_load(:observations).where(
     observations: { id: Observation.pluck_from_each_station(limit) } 
    ) 
    end 
end 

Observation.pluck_from_each_stationは、IDの配列を返します。 observationsテーブルには何千もの行が含まれているので、レールを熱心に読み込んで何千ものレコードをロードする必要があります。

この方法は、の観測結果がであるかどうかにかかわらず、すべてのステーションを返す必要があります。しかし、現在はそうではありません。結合テーブルかどうかのいずれかの結果がある天気を私の理解LEFT OUTER JOINから

it "includes stations that have no observations" do 
    new_station = create(:station) 
    stations = Station.with_observations(2) 
    expect(stations).to include new_station # fails 
end 

は、すべての行を返す必要があります。これが期待どおりに機能しないのはなぜですか?

eager_load(:observations).where(
    '"observations"."id" is null or "observations"."id" in (?)', Observation.pluck_from_each_station(limit) 
) 

それは論理的に次のとおりです。uはレコードを除いているためleft join"observations"."id"がnullであり、私はそれが起こると思います

SELECT "stations"."id" AS t0_r0, 
     "stations"."name" AS t0_r1, 
     "stations"."hw_id" AS t0_r2, 
     "stations"."latitude" AS t0_r3, 
     "stations"."longitude" AS t0_r4, 
     "stations"."balance" AS t0_r5, 
     "stations"."timezone" AS t0_r6, 
     "stations"."user_id" AS t0_r7, 
     "stations"."created_at" AS t0_r8, 
     "stations"."updated_at" AS t0_r9, 
     "stations"."slug" AS t0_r10, 
     "stations"."speed_calibration" AS t0_r11, 
     "stations"."firmware_version" AS t0_r12, 
     "stations"."gsm_software" AS t0_r13, 
     "stations"."description" AS t0_r14, 
     "stations"."sampling_rate" AS t0_r15, 
     "stations"."status" AS t0_r16, 
     "observations"."id" AS t1_r0, 
     "observations"."station_id" AS t1_r1, 
     "observations"."speed" AS t1_r2, 
     "observations"."direction" AS t1_r3, 
     "observations"."max_wind_speed" AS t1_r4, 
     "observations"."min_wind_speed" AS t1_r5, 
     "observations"."temperature" AS t1_r6, 
     "observations"."created_at" AS t1_r7, 
     "observations"."updated_at" AS t1_r8, 
     "observations"."speed_calibration" AS t1_r9 
FROM "stations" 
     LEFT OUTER JOIN 
     "observations" 
     ON "observations"."station_id" = "stations"."id" 
WHERE "observations"."id" IN (450, 500, 550, 600, 650, 700, 750, 800); 
+1

'' observations "。" id "IN(..)' ''句の中で、 'WHERE'節ではないはずです。 – sagi

答えて

1

この

は、生成されたSQLの例です。 2つの条件で同じ left joinと同じですが、レールにはこの機能がありませんので、 where句を使用して回避することができます。

+0

これは、左結合の右のテーブルの条件を 'ON'節に置く必要があるためです。それらが 'WHERE'節にあるとき、結合は内部結合に変換されます。 – sagi

+0

@sagi:はい、それは 'where'節でも行うことができます。 – potashin

+0

そうですが、それは悪い習慣です。 – sagi

関連する問題