I using Rails 6 with Postgres and having issues deleting a nested model. A random insert statement gets generated after the association has been deleted.
Let me explain my set up.
Migrations
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
Models
class Entry < ApplicationRecord
has_one :card, dependent: :destroy
accepts_nested_attributes_for :card, allow_destroy: true
end
class Card < ApplicationRecord
belongs_to :entry
end
Controller
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
Request Params
Parameters: {"authenticity_token"=>"CQ...Ucw==", "entry"=>{"card_attributes"=>{"_destroy"=>"true"}}, "id"=>"1"}
These are the logs
(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
Why is insert being generated after the delete call? It's not even a rollback.
Note: I have tried both null:true and null:false in the Cards belongs_to migration. I also tried setting optional:true in the belongs_to :entry statement in the Card model
Unless you include an id
in card_attributes
then Rails sees this as a new record, so it just replaces the has_one
with a newly created Card
for you (which because of your dependent: :destroy
option deletes the existing associated Card
).
Best to use a form.fields_for :card
block in your form partial/view, which will automatically add the hidden id
tag for an existing Card.