Обновление Rails включает изменение поведения метода - PullRequest
0 голосов
/ 03 января 2019

Я копал пару дней и не нашел хорошего объяснения этому изменению поведения.Я нахожусь в процессе обновления приложения Rails с 3.2 до 5.2, это код в проходящем тесте из моего приложения rails 3.

 ps = Project.includes(:rentals).where('rentals.id IN (?)', [1,2,3,4])

это выплевывает большой старый SQL-запрос на левые соединения.
но если я делаю тот же запрос в рельсах 5, я получаю ошибку mysql

ActiveRecord::StatementInvalid (Mysql2::Error: Unknown column 'rentals.id' in 'where clause': SELECT  `projects`.* FROM `projects` WHERE (rentals.id IN (1,2,3,4)) LIMIT 11 /*application:ConHQ*/)

Я понимаю, что включает в себя то, что он должен выполнять отдельные запросы, если на включенную таблицу не ссылаются в предложении where, вв этом случае он должен сделать левое соединение.но, похоже, здесь этого не происходит.Использование eager_load работает в этом случае:

 ps = Project.eager_load(:rentals).where('rentals.id IN (?)', [1,2,3,4])

, но я подумал, что включает в себя то же самое.
Я также заметил, что иногда включает в себя выполняет тот же запрос, что и eager_load

@project = Project.find(174)
@project.rentals.eager_load(:equipment_name).where('equipment_names.id IN (?)', [1,2,3,4])
@project.rentals.includes(:equipment_name).where('equipment_names.id IN (?)', [1,2,3,4])

В этом случае eager_load и включает оба выполняют левое соединение.Я не нашел никакой документации, которая объясняет, почему в таких ситуациях действует по-разному.как именно включает в себя выбрать запрос, который он выполняет?

1 Ответ

0 голосов
/ 03 января 2019

includes просто сообщает ActiveRecord, что данные должны быть загружены с нетерпением, но он может достичь этого, как ему угодно.Если вы хотите сослаться на другую модель в запросе, вам также придется использовать references(:rentals).

ActiveRecord API чрезвычайно мощен и универсален, но, как это часто бывает в Ruby и его библиотекахЕсть много способов чего-то достичь.В этом случае вы также можете использовать merge для объединения в другое отношение.

rentals = Rental.where(id: [1,2,3,4])
projects = Project.joins(:rentals).merge(rentals) # you can additionally add includes, too, if you want to access the rentals

Это дает дополнительное преимущество: вам не нужно заботиться о названии таблицы модели Rental.

...