rwehresmann
rwehresmann

Reputation: 1178

insert or update on table violated foreign key constraint (error)

I have a polymorphic association of User and AuthorizedReceiver using PersonalInfo.

class User < ApplicationRecord
  has_many :authorized_receivers
  has_one :personal_info, as: :info_owner
end

class AuthorizedReceiver < ApplicationRecord
  belongs_to :user
  has_one :personal_info, as: :info_owner
end

class PersonalInfo < ApplicationRecord
  belongs_to :info_owner, polymorphic: true
end

When I create my first AuthorizedReceiver to the user, and try to update the PersonalInfo of this AuthorizedReceiver, I have success. However, when I create the second AuthorizedReceiver and try to update its PersonalInfo, I have the following error:

ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation: ERROR:  insert or update on table "personal_infos" violates foreign key constraint "fk_rails_796da13f22"
DETAIL:  Key (info_owner_id)=(2) is not present in table "users".
: INSERT INTO "personal_infos" ("info_owner_id", "full_name", "created_at", "updated_at", "info_owner_type") VALUES ($1, $2, $3, $4, $5) RETURNING "id"

What am I doing wrong?

PS: The same doesn't happens if I do the same with User (i.e, try to update the PersonalInfo of a second user succeed).

EDIT:

class CreatePersonalInfos < ActiveRecord::Migration[5.1]
  def up
    create_table :personal_infos do |t|
      t.references :user, foreign_key: true, index: true, unique: true
  end
end


class AddInfoOwnerToPersonalInfos < ActiveRecord::Migration[5.1]
  def up
    rename_column :personal_infos, :user_id, :info_owner_id
    add_column :personal_infos, :info_owner_type, :string

    add_index :personal_infos, [ :info_owner_type, :info_owner_id]

    PersonalInfo.update_all(info_owner_type: 'User')

    change_column :personal_infos, :info_owner_type, :string, null: false
  end

  def down
    rename_column :personal_infos, :info_owner_id, :user_id
    remove_column :personal_infos, :info_owner_type
  end
end

That resulted in a wrong fk constraint that still pointing to users:

ALTER TABLE ONLY public.personal_infos
    ADD CONSTRAINT fk_rails_796da13f22 FOREIGN KEY (info_owner_id) REFERENCES public.users(id);

Upvotes: 2

Views: 2327

Answers (1)

AndreDurao
AndreDurao

Reputation: 5795

Like both me and @PavelMikhailyuk commented:

you just renamed the column to info_owner_id

rename_column :personal_infos, :user_id, :info_owner_id

You also need to remove the foreign key:

Since you changed the column name, Rails may not find the association automatically, then you may try to remove the foreign_key with a migration like this:

remove_foreign_key :personal_infos, column: :info_owner_id

Upvotes: 2

Related Questions