Метод update_all не работает для связанных записей
У меня есть две модели, и связь между ними has_and_belongs_to_many
, Мне нужно провести рефакторинг кода, так как он вызывает n + 1 запросов.
Проблема: n+1 запросов
1. Задача
class Task < ActiveRecord::Base
has_and_belongs_to_many :user_groups
end
2. UserGroup
class UserGroup < ActiveRecord::Base
has_and_belongs_to_many :tasks
end
Требование:
Назначить задачи для групп пользователей
Предыдущий код контроллера:
task_ids.each do |task_id|
find(task_id).update_attributes! user_group_ids: params[:user_group_ids], release_date: params[:release_date]
end
Моя попытка:
tasks = Task.where(id: task_ids)
tasks.update_all(user_group_ids: params[:user_group_ids], release_date: params[:release_date])
Ошибка:
ActiveRecord:: StatementInvalid (PG:: UndefinedColumn: ERROR: столбец "user_group_ids" отношения "tasks" не существует
Запрос сгенерирован:
SQL (0,6 мс) ОБНОВЛЕНИЕ "заданий" SET "user_group_ids" = 4, "release_date" = '2017-04-27 07:40:26.525357' ГДЕ "tasks". "Удаленный_at" IS NULL И "tasks". "Id" = 47394
Пожалуйста, дайте мне знать, как это сделать с update_all
1 ответ
Вы не можете массово назначить ассоциацию, используя update_all
, update_all
выполняет один запрос UPDATE, но для ассоциации вам действительно нужен запрос INSERT для вставки связанных моделей. Вы можете использовать драгоценный камень, как bulk_insert
вставить все объекты объединения одним запросом INSERT https://github.com/jamis/bulk_insert
Почему вам нужно было создать модель UserGroup? Это не так, как мы используем habtm
отношения.
И твоя модель Task
посреди всего этого, как бы смутило меня. Что нужно сделать? Я подозреваю, что у вас нет habtm
отношения в Task
,
Для ошибки, которую вы получаете, это вполне понятно. У вас нет атрибута (столбца) с именем user_group_ids
в tasks
Таблица. А также, для habtm
отношения, этот атрибут user_group_ids
кажется, с ошибкой для меня.
Во всяком случае, для habtm
отношения, если у вашего пользователя много групп, а у группы может быть много пользователей, вы на правильном пути, однако для Ruby on Rails есть два способа сделать это.
Если вам не нужно управлять другими данными (атрибутами отношений) в таблице отношений:
- Тогда вам понадобится только стол
groups_users
, в твоем случае. Рельсы будут искатьhabtm
таблица отношений в алфавитном порядке.
- Тогда вам понадобится только стол
Если твой
groups_users
отношение содержит любые другие данные, кроме ссылочных идентификаторов модели, тогда вам лучше использоватьhas_many :through
отношения.В этом случае ваша таблица UserGroup (обратите внимание на особенность) будет содержать дополнительные данные, которые вам нужны в отношениях. Затем вы заявляете следующее:
User
Модель заявит:has_many :groups, through: :user_groups
Group
Модель заявит:has_many :users, through: :user_groups
UserGroup
модель:belongs_to :user
а такжеbelongs_to :group
, Будьте осторожны, чтобы не индексировать ни один из них как уникальный, уровень базы данных или уровень приложения.
Для более подробной информации проверьте http://guides.rubyonrails.org/association_basics.html
Надеюсь, вы получите свои результаты!