my schema.db
create_table 'pet', force: :cascade do |t|
t.string 'name'
t.datetime 'created_at', precision: 6, null: false
t.datetime 'updated_at', precision: 6, null: false
end
create_table 'user', force: :cascade do |t|
t.string 'name'
t.references :pet, index: true, foreign_key: { on_delete: :nullify }
t.datetime 'created_at', precision: 6, null: false
t.datetime 'updated_at', precision: 6, null: false
end
user model
class User < ApplicationRecord
has_one :pet, foreign_key: :id, dependent: :destroy
end
pet model
class Pet < ApplicationRecord
belongs_to :user, optional: true
end
show.erb
<%= link_to t('delete'), user_path(id: @user.id), method: :delete %>
<%= link_to t('.pet_delete'), pet_path(@auser.pet_id), method: :delete %>
user controller
def destroy
User.destroy(params[:id])
redirect_to users_path
end
pet controller
def destroy
Pet.destroy(params[:id])
redirect_to users_path
end
Problem : if i delete user id 5 with pet id 5, dependent destroy works well and it deletes (user id 5) & (pet id 5)
if i have user id 5 with pet id nil, and user id 4 with pet id 5, when i delete user id 5, user 5 deleted with user4's pet (pet id 5) so leftover result -> user id 5 delete, user id 4 with nil pet
something is wrong but i can't find what is problem. dependent destroy can only find same userId and petId in the same time.
i expecting if i delete user id 3 with pet id 1, want to make delete well i tried change position of dependent destroy(on pet model), change schema.rb's on_delete nullify to delete but not worked.
CodePudding user response:
The problem is that you specified id
as a foreign key.
class User < ApplicationRecord
has_one :pet, foreign_key: :id, dependent: :destroy
end
You need to specify user_id
instead:
class User < ApplicationRecord
has_one :pet, foreign_key: :user_id, dependent: :destroy
end
But, in a simple case like this you don't need to specify foreign key at all. As long as you have a column named user_id
in pets
table it will just work, since Rails automatically assumes that the foreign key should be <model>_id
.
Also, please keep in mind that the foreign key should be added to the child, not the parent. So, you need to add user_id
to pets
table, not pet_id
to the users
table.
In the end, your schema.rb
should look something like this:
create_table 'pet', force: :cascade do |t|
t.string 'name'
t.datetime 'created_at', precision: 6, null: false
t.datetime 'updated_at', precision: 6, null: false
t.references :user, index: true, foreign_key: { on_delete: :nullify } # <== this should be added
end
create_table 'user', force: :cascade do |t|
t.string 'name'
# t.references :pet, index: true, foreign_key: { on_delete: :nullify } <== this should be removed
t.datetime 'created_at', precision: 6, null: false
t.datetime 'updated_at', precision: 6, null: false
end