Метод 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 ответ

Ваше решение (не вызывая N+1) является activerecord-import

Вы не можете массово назначить ассоциацию, используя 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 есть два способа сделать это.

  1. Если вам не нужно управлять другими данными (атрибутами отношений) в таблице отношений:

    • Тогда вам понадобится только стол groups_users, в твоем случае. Рельсы будут искать habtm таблица отношений в алфавитном порядке.
  2. Если твой 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

Надеюсь, вы получите свои результаты!

Другие вопросы по тегам