Я использую метод AR includes
выполнить левое внешнее соединение между объектами пользователя и Строительство, где пользователь может или не может иметь ассоциацию здание:Неожиданное поведение с ActiveRecord включает
users = User.includes(:building).references(:buildings)
Поскольку я использую references
, любые связанные объекты здания будут загружены.
Мое предположение состояло в том, что я мог бы выполнить итерацию по списку пользователей и проверить, связано ли с ним здание, связанное с ними, без запуска дополнительных запросов, но я вижу, что на самом деле всякий раз, когда я пытаюсь получить доступ к зданию свойство пользователя, у которого его нет, AR делает другой вызов SQL, чтобы попытаться восстановить это здание (хотя при последующих попытках он просто вернет нуль).
Эти запросы, очевидно, излишни, поскольку ассоциация была бы загружена во время первоначального соединения и, кажется, побеждает целую цель активной загрузки с включением/ссылками, так как теперь я просматриваю N раз число запросов, равных к числу пустых ассоциаций.
users.each do | user |
# This will trigger a new query when building is not present:
# SELECT "buildings".* FROM "buildings" WHERE "buildings"."address" = $1 LIMIT 1 [["address", "123 my street"]]
if user.building
puts 'User has building'
else
puts 'User has no building'
end
end
Класс пользователя:
class User < ActiveRecord::Base
belongs_to :building, foreign_key: 'residence_id'
end
Есть ли способ, чтобы проверить наличие строительной ассоциации пользователей без запуска дополнительных запросов?
на рельсах 4.2.0/POSTGRES
UPDATE:
Спасибо @BoraMa за составление этого test. Похоже, мы получаем различное поведение на все последние версии Rails:
OUTPUT (РЕЛЬСЫ 4.2.0):
User 1 has building
User 2 has building
User 3 has no building
D, [2016-05-26T11:48:38.147316 #11910] DEBUG -- : Building Load (0.2ms) SELECT "buildings".* FROM "buildings" WHERE "buildings"."id" = $1 LIMIT 1 [["id", 123]]
User 4 has no building
OUTPUT (РЕЛЬСЫ 4.2.6)
User 1 has building
User 2 has building
User 3 has no building
User 4 has no building
OUTPUT (РЕЛЬСЫ 5.0 .0)
User 1 has building
User 2 has building
User 3 has no building
User 4 has no building
Возьмите Визитки:
- Этот вопрос был ограничен «оборванным внешние ключи (т.е. столбец residence_id не ноль, но там нет соответствующего здания объекта)» (БЛАГОДАРЯ @FrederickCheung)
- Проблема была решена, как в Rails 4.2. 6
Я бы ожидал ошибку, похожую на «ActiveRecord :: AssociationNotFoundError: Ассоциация с именем« здания »не была найдена на пользователе». Можете ли вы подтвердить синтаксис запроса, а также определение User-> Building association? – messanjah
@messanjah Лично я ожидал бы, что 'user.building' вернет nil, если ассоциация не существует, и это то, что происходит при последующих вызовах, но при первом вызове он всегда запускает SQL-запрос. – Yarin
Странно, я не наблюдаю этого поведения - мои ничтожные ассоциации просто возвращают нуль, без дальнейших запросов. Является ли код, который вы задали в вопросе, действительно минимальным рабочим примером проблемы? – BoraMa