Рельсы. Отношение многие ко многим устанавливается через вложенные атрибуты

Я пытался понять, как установить отношение has_many, through:, используя вложенные атрибуты.

У меня есть следующие модели:

user.rb

class User < ApplicationRecord
   has_many :user_tags
   has_many :tags, through: :user_tags

   accepts_nested_attributes_for :user_tags,
                            allow_destroy: true,
                            reject_if: :all_blank
end

user_tag.rb

class UserTag < ApplicationRecord
  belongs_to :tag
  belongs_to :user

  accepts_nested_attributes_for :tag

  validates :tag, :user, presence: true
  validates :tag, :uniqueness => {:scope => :user}
  validates :user, :uniqueness => {:scope => :tag}
end

tag.rb

class Tag < ApplicationRecord
  has_many :user_tags
  has_many :users, through: :user_tags

  validates :title, presence: true, uniqueness: true
end

Связанная схема

  create_table "user_tags", id: :integer, force: :cascade do |t|
    t.integer  "user_id"
    t.integer  "tag_id"
    t.index ["tag_id"], name: "index_user_tags_on_tag_id", using: :btree
    t.index ["user_id"], name: "index_user_tags_on_user_id", using: :btree
  end

  create_table "tags", id: :integer, force: :cascade do |t|
    t.string   "title"
    t.string   "language"
    t.integer  "type"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

Все теги предопределены и не могут быть изменены. Мне нужно только установить и уничтожить связь между tags и users в модели user_tag, в действиях пользователя по созданию/обновлению через вложенные атрибуты.

Что-то типа:

params = { user: {
      user_tags_attributes: [
          { id: 1, _destroy: '1' }, # this will destroy association
          { tag_id: 1 }, # this will create new association with tag, which id=1 if tag present
          { tag_title: 'name' } # this will create new association with tag, which title='name' if tag present
      ]
  }}

user.update_attributes(params[:user])

Точная проблема заключается в том, что я не могу создать ассоциацию ONYL, но я могу создавать или обновлять теги через ассоциации.

Я использую Rails 5.0


person Derk153    schedule 31.05.2016    source источник
comment
С какой именно проблемой вы столкнулись? Не могли бы вы также опубликовать соответствующую часть schema.rb.   -  person Jan Bussieck    schedule 31.05.2016
comment
@JanBussieck: я добавил schema.rb к своему вопросу. Проблема в том, что я не могу создать ассоциацию ONYL. При выполнении user.update_attributes(user_tags_attributes: [{tag_id: 1}]) ожидал, что для пользователя будет создана ассоциация для тега с ID=1, но получаю ошибку. user.errors.messages => {:"user_tags.tag.title"=>["has already been taken"]} Я предполагаю, что он пытается создать новый тег. Таблица UserTag пуста, и у пользователя нет связанных тегов   -  person Derk153    schedule 31.05.2016
comment
Ну вот и все: вы получаете сообщение об ошибке, потому что пытаетесь создать тег с заголовком, который уже занят, поэтому ваша проверка validates :title, presence: true, uniqueness: true предотвращает создание записи.   -  person Jan Bussieck    schedule 31.05.2016


Ответы (1)


Я нашел решение своей проблемы. У меня ошибка в UserTag валидации.

Я изменился

  validates :tag, :uniqueness => {:scope => :user}
  validates :user, :uniqueness => {:scope => :tag}

to

  validates :tag_id, :uniqueness => {:scope => :user_id}
  validates :user_id, :uniqueness => {:scope => :tag_id}

и назначение тегов работает.

Remans, чтобы найти решение, как разрушить ассоциацию по tag_id, без идентификатора ассоциации

person Derk153    schedule 31.05.2016