Я предпочитаю начинать с запроса с модели, которую хочу получить. Вместо того, чтобы получать «коллекцию из коллекции коллекций», вы можете...
Присоедините Location
ко всем событиям, чтобы получить все Event
, чьи Location
соответствуют определенным условиям. В большинстве случаев область действия — это просто набор условий, которые могут быть merge
d.
Вот так:
Event.joins(:location) # Results in `INNER JOIN`
.merge(current_user_location.nearby) # Adds in the conditions for locations
Но все не так просто!
Geocoder делает очень сложный select
под капотом и добавляет некоторые полезные поля, такие как distance
, которые зависят от точки, которая была передана в область видимости. Мы не можем просто так их потерять, верно? Запрос перестанет иметь какой-либо смысл.
Можно сделать INNER JOIN
очень странным способом: указав FROM
-клаузу для получения данных из двух таблиц (подробнее об этом позже) и указав условие соединения в пункте WHERE
. Для этого нам понадобится немного Arel, так что давайте заранее вытащим таблицы:
locations = Location.arel_table
events = Event .arel_table # Yeah, call me an indentation maniac
А теперь загвоздка: вместо таблицы locations
мы будем использовать результаты подзапроса, сформированного current_user_location.nearby
. Как? Мы снабдим from
массивом вещей, которые мы хотим использовать:
Event.from([current_user_location.nearby.as('locations'), events])
# ^ an array, yeah!
Что мы имеем здесь:
select events.* from (geocoder subquery) locations, events
Что теперь? Условие присоединения. Как я уже сказал, поскольку мы делаем странное соединение, мы укажем условие соединения в where
. Мы должны.
Event.from([current_user_location.nearby.as('locations'), events])
.where(location_id: locations[:id])
... и это, вероятно, должно работать нормально. Сделано полностью базой данных по крайней мере.
person
D-side
schedule
17.06.2015