Rails 6: Невозможно удалить вложенную модель. Оператор случайной вставки

Я использую Rails 6 с Postgres и не могу удалить вложенную модель. После удаления связи создается случайный оператор вставки.

Позвольте мне объяснить мою установку.

Миграции

class CreateEntries < ActiveRecord::Migration[6.0]
  def change
    create_table :entries do |t|
      t.string :name
      t.timestamps
    end
  end
end

class Cards < ActiveRecord::Migration[6.0]
  def change
    create_table :cards do |t|
      t.string :card_number
      t.belongs_to :entry, null: true, foreign_key: true
      t.timestamps
    end
  end
end

Модели

class Entry < ApplicationRecord
  has_one :card, dependent: :destroy
  accepts_nested_attributes_for :card, allow_destroy: true
end

class Card < ApplicationRecord
  belongs_to :entry
end

Контроллер

class EntriesController < ApplicationController
    before_action :set_entry

    def update
       @entry.update(entry_params)
    end

    def set_entry
       @entry = Entry.find(params[:id])
    end

    def entry_params
      params.require(:entry).permit(:name,
        card_attributes: [:id, :card_number, :_destroy]
      )
    end
end

Параметры запроса

Parameters: {"authenticity_token"=>"CQ...Ucw==", "entry"=>{"card_attributes"=>{"_destroy"=>"true"}}, "id"=>"1"}

Это журналы

(0.2ms)  BEGIN

ConcessionCard Load (0.2ms)  SELECT "cards".* FROM "cards" WHERE "cards"."entry_id" = $1 LIMIT $2  [["entry_id", 1], ["LIMIT", 1]]

Card Destroy (0.4ms)  DELETE FROM "cards" WHERE "cards"."id" = $1  [["id", 2]]

Card Create (0.6ms)  INSERT INTO "cards" ("entry_id", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id"  [["entry_id", 1], ["created_at", "2019-09-06 13:50:41.100718"], ["updated_at", "2019-09-06 13:50:41.100718"]]

(0.3ms)  COMMIT

Почему после вызова удаления создается вставка? Это даже не откат.

Примечание. Я пробовал как null: true, так и null: false при миграции Cards own_to. Я также пробовал установить optional: true в операторе own_to: entry в модели Card


person user346443    schedule 06.09.2019    source источник
comment
Пожалуйста, помогите, я схожу с ума.   -  person user346443    schedule 06.09.2019
comment
У вас есть код модели Entry, который устанавливает соответствующую карту? Можете попробовать заменить вызов update на @entry.attributes = ...; @entry.save? вы можете использовать byebug или pry rails для проверки объекта перед вызовом save.   -  person arieljuod    schedule 06.09.2019


Ответы (1)


Если вы не включите id в card_attributes, тогда Rails увидит это как новую запись, поэтому он просто заменит has_one вновь созданным Card для вас (который из-за вашей опции dependent: :destroy удаляет существующий связанный Card).

Лучше всего использовать блок form.fields_for :card в вашей форме partial / view, который автоматически добавит скрытый тег id для существующей карты.

person smathy    schedule 06.09.2019
comment
Спасибо за ответ, очень ценю вашу помощь. Операция удаления не выполняется, если я включаю идентификатор карты в атрибуты карты. Вот параметры: entry = ›{card_attributes =› {id = ›2, _destroy =› true}}. Однако, если идентификатор карты исключен из атрибутов карты, то выполняется операция удаления, за которой следует операция вставки, как вы предложили. - person user346443; 07.09.2019
comment
Спасибо, сэр Смати. Это решило ее. Я с удовольствием куплю тебе пива. Пожалуйста, дайте мне знать, как это сделать. - person user346443; 07.09.2019