Had a really difficult time titling this one – please adjust as you see fit.
Essentially, I would like to do this in Rails:
SELECT airports.*, observations.*
FROM airports
LEFT OUTER JOIN observations ON airports.id = observations.airport_id
WHERE airports.latitude > 51 AND airports.latitude < 52 AND airports.longitude > 0.5 AND airports.longitude < 2
AND (observations.month = 10 OR observations.month IS NULL)
This gives me a nice result with a list of airports in a bounding box and their observations, whether they have any or not.
How can I do that in Rails 3? Whatever I try I only get airports in the resulting array, with no observations at all. I can get rails to form the SQL by doing an includes and specifying a condition, like so:
Airport.includes(:observations)
.where('observations.month = 10 OR observations.month IS NULL')
.where("airports.latitude > 51 AND airports.latitude < 52 AND airports.longitude > 0.5 AND airports.longitude < 2")
This is great, it gives me sql which does the same as what I wrote above:
SELECT `airports`.`id` AS t0_r0, `airports`.`name` AS t0_r1, `airports`.`city` AS t0_r2,
`airports`.`country` AS t0_r3, `airports`.`iata` AS t0_r4, `airports`.`icao` AS t0_r5,
`airports`.`latitude` AS t0_r6, `airports`.`longitude` AS t0_r7, `airports`.`altitude` AS
t0_r8, `airports`.`timezone` AS t0_r9, `airports`.`dst` AS t0_r10, `airports`.`created_at`
AS t0_r11, `airports`.`updated_at` AS t0_r12, `observations`.`id` AS t1_r0,
`observations`.`airport_id` AS t1_r1, `observations`.`month` AS t1_r2,
`observations`.`temperature_max` AS t1_r3, `observations`.`temperature_min` AS t1_r4,
`observations`.`chance_of_rain` AS t1_r5, `observations`.`rain_avg` AS t1_r6,
`observations`.`dew_point` AS t1_r7, `observations`.`created_at` AS t1_r8,
`observations`.`updated_at` AS t1_r9, `observations`.`fortnight` AS t1_r10 FROM `airports`
LEFT OUTER JOIN `observations` ON `observations`.`airport_id` = `airports`.`id` WHERE
(observations.month = 10 OR observations.month IS NULL) AND (airports.latitude > 51 AND
airports.latitude < 52 AND airports.longitude > 0.5 AND airports.longitude < 2)
But the record result is disappointing. No observations (Southend should have observations):
[#<Airport id: 14343, name: "Southend", city: "Southend", country: "United Kingdom",
iata: "SEN", icao: "EGMC", latitude: 51.5714, longitude: 0.695556, altitude: 49,
timezone: 0, dst: "E", created_at: "2011-12-08 11:27:28", updated_at: "2011-12-08
11:27:28">, #<Airport id: 14345, name: "Manston", city: "Manston", country: "United
Kingdom", iata: "MSE", icao: "EGMH", latitude: 51.3422, longitude: 1.34611, altitude:
178, timezone: 0, dst: "E", created_at: "2011-12-08 11:27:28", updated_at: "2011-12-08
11:27:28">, #<Airport id: 15292, name: "Ashford", city: "Lympne", country: "United
Kingdom", iata: "LYM", icao: "EGMK", latitude: 51.0833, longitude: 1.01667, altitude:
351, timezone: 0, dst: "E", created_at: "2011-12-08 11:27:29", updated_at: "2011-12-08
11:27:29">, #<Airport id: 20740, name: "Ferry Port", city: "Dover", country: "United
Kingdom", iata: nil, icao: "\\N", latitude: 51.1269, longitude: 1.33975, altitude: 6,
timezone: 0, dst: "E", created_at: "2011-12-08 11:27:38", updated_at: "2011-12-08 11:27:38">]
It seems I’m missing something fundamental here. Any clues? Thanks.
The resulting objects won’t appear in the result set, but are eagerly loaded to avoid querying for the objects when needed.
http://guides.rubyonrails.org/active_record_querying.html