In an effort to properly handle Postgres's ForeignKeyViolation warnings, I've gone through each of my models and added on_delete: commands as shown below.
The format I'm following is
add_foreign_key <:named_table>, <:related_table>, on_delete: :cascade
However, after making these changes and running rails db:reset
I notice these extra parameters are not being passed into the resulting schema.rb file and I still receive the abovementioned error when trying to delete an image.
Is there something I'm doing wrong either in my procedure or my syntax? Thank you in advance!
12345_create_document_images.rb
class CreateDocumentImages < ActiveRecord::Migration[5.1]
def change
create_table :document_images do |t|
t.references :document, foreign_key: true
t.references :image, foreign_key: true
t.timestamps
end
add_foreign_key :document_images, :documents, on_delete: :cascade
add_foreign_key :document_images, :images, on_delete: :cascade
end
end
schema.rb
add_foreign_key "document_images", "images"
add_foreign_key "document_images", "documents"
When you say this:
t.references :document, foreign_key: true
The foreign_key: true
option creates the same foreign key that:
add_foreign_key :document_images, :documents, on_delete: :cascade
does. When the add_foreign_key
method executes, the FK already exists so it should trigger an PG::DuplicateObject
exception at least it does for me. I'm not sure why you're not getting an exception but that doesn't matter, what does matter is that the FK from create_table
will be there before you try to add an FK with on_delete: :cascade
via your add_foreign_key
calls.
The solution is to let t.references
create the FK with on_delete: :cascade
and leave out the explicit add_foreign_key
calls:
class CreateDocumentImages < ActiveRecord::Migration[5.1]
def change
create_table :document_images do |t|
t.references :document, foreign_key: { on_delete: :cascade }
t.references :image, foreign_key: { on_delete: :cascade}
t.timestamps
end
end
end
I also renamed the migration to match what it is really doing.
Added by Spectator6: Something else that @mu_is_too_short introduced me to is the use of rails db:migrate:redo
which led me to also learn about rails db:migrate:reset
. Previously, I had only been using rails db:reset
, but the moment I implemented his suggestions and then ran rails db:migration:reset
followed by rails db:reset
, everything clicked! The schema reflected the new database triggers on the foreign_key and trying out the functionality in development worked as expected. Very cool! All props to @mu_is_too_short!