Rails 3: внутреннее объединение с ассоциациями

#ruby-on-rails #activerecord #left-join

#ruby-on-rails #activerecord #левое соединение

Вопрос:

Я немного застрял на проблеме с активным запросом записи. Я хотел бы выполнить левое соединение вместо внутреннего соединения в запросе, но результаты joins метода возвращают только внутреннее соединение.

 Entry.
  joins(:measurements => :measurement_type).
  sum(:value, :conditions => ['name = ?','Calories'])
  

Сложность заключается в том, что :measurements имеет отношение belongs_to к :measurement_type , в котором находится столбец name.

Прямо сейчас это возвращает суммы только для пользователей, у которых есть food_posts. Цель состоит в том, чтобы возвращать суммы для всех пользователей. Пользователи, у которых нет записи о еде, получат нулевую сумму.

Я пытался использовать Google и искать другие сообщения здесь, но не нашел ответа. Есть предложения?

Также я использую SQLite в своей среде разработки и Postgresql для производства.

Ответ №1:

Если вы хотите выполнить левое соединение вместо внутреннего соединения, вам нужно использовать пользовательские «фрагменты sql»

В вашем примере,

 relation.joins("left join measurements on measurements.id = measurement_type.measurements_id")
  

Или что-то в этом роде, зависящее от ваших настроек.

Этот учебник довольно четко подводит итог.

Комментарии:

1. Спасибо! Похоже, мне пришлось выполнить более длинный запрос, чем ваш пример, для дополнительной ассоциации, на чем я и застрял. Что могло бы быть более кратким, но вот что у меня получилось: relation.joins("LEFT JOIN measurements ON measurements.entry_id = entries.id").joins("INNER JOIN measurement_types ON measurement_types.id = measurements.measurement_type_id")

2. Я так и подозревал. Я не был на 100% уверен в вашей схеме DB из вашего исходного сообщения. P.S. Если вопрос решает вашу проблему, не забудьте принять 🙂

Ответ №2:

MetaWhere gem имеет поддержку внешних соединений, среди многих других преимуществ:

https://github.com/ernie/meta_where

Комментарии:

1. Для Rails 3.1 и выше заменено на Squeel . У Райана Бейтса есть видеоролик об этом .