Я настроил три модели: User, List и UserList - последняя представляет собой модель соединения между User и List в отношении has_many_through
.
Я пытаюсь настроитьто, что я думаю, должно быть довольно ванильным ограничением уникальности - но это не совсем работает.Буду признателен за ваше руководство / совет, пожалуйста!
Технические подробности
У меня есть 3 модели:
class User < ApplicationRecord
has_many :user_lists
has_many :lists, through: :user_lists, dependent: :destroy
End
class List < ApplicationRecord
has_many :user_lists
has_many :users, through: :user_lists, dependent: :destroy
# no duplicate titles in the List table
validates :title, uniqueness: true
End
class UserList < ApplicationRecord
belongs_to :list
belongs_to :user
# a given user can only have one copy of a list item
validates :list_id, uniqueness: { scope: :user_id }
end
Как видите, я бы хотел, чтобы элементы списка были уникальнымина основании их названия.Другими словами, если пользователь Адам добавляет Список с заголовком «Темный рыцарь», то пользователь Беатрис, добавляющий Список с заголовком «Темный рыцарь», на самом деле не должен создавать новую запись Списка - он должен просто создавать новую / отличнуюАссоциация UserList, указывающая на ранее созданный элемент списка.
(Несколько касательно, но я также добавил уникальный индекс в таблицу, поскольку, как я понимаю, это позволяет избежать условия гонки)
class AddIndexToUserLists < ActiveRecord::Migration[5.2]
def change
add_index :user_lists, [:user_id, :list_id], unique: true
end
end
Вотгде все идет не так.
Как пользователь Адам, я вхожу в систему и добавляю новый заголовок "Темный рыцарь" в свой список.
Вот действие контроллера (допустим, что current_user правильнополучает Адама):
# POST /lists
def create
@list = current_user.lists.find_or_create_by!(list_params)
end
Это правильно приводит к созданию новой записи списка и связанной записи UserList.Ура!
Как Адам, если я попытаюсь добавить тот же самый заголовок "Темный рыцарь", в мой список снова ничего не произойдет - в том числе без ошибок на консоли.Ура!
Однако - как пользователь Беатрис, если я войду в систему и попытаюсь добавить «Темного рыцаря» в свой список, я теперь получаю сообщение об ошибке в консоли:
POST http://localhost:3000/api/v1/lists 422 (Unprocessable Entity)
Моя отладка и гипотеза
Если я уберу ограничение уникальности для List.title, эта ошибка исчезнет, и Беатрис сможет добавить «Темный рыцарь» в свой список.
Тем не менее, List содержит две записи под названием «Темный рыцарь», которые кажутся излишними.
Что касается Адама, то, возможно, current_user.lists.find_or_create_by!(list_params)
в моем действии контроллера находит существующее "Темное"Рыцарь "список, связанный с моим текущим пользователем, и понимая, что он существует - таким образом, не вызывая действие создания.
Тогда, как Беатрис, кажется, что то же самое действие контроллера не находит существующий список" Темного рыцаря "элемент, связанный с моим текущим пользователем, и поэтому он пытается инициировать действие создания.
Однако это действие создания пытается создать новый элемент списка с уже существующим заголовком.- то есть это противоречит проверке уникальности модели List.rb.
Я не уверен, как изменить это действие find_or_create_by или проверки модели, чтобы обеспечить для Beatrice новую запись / ассоциацию UserListсоздается, но не новая запись списка (поскольку она уже существует).
Такое чувство, что, может быть, я упускаю что-то простое здесь.А может и нет.Был бы очень признателен за некоторые рекомендации о том, как действовать.Спасибо!