Skip to content

Recursive import with has_many association that has a custom primary_key fails #878

@difernandez

Description

@difernandez

Problem

The failure comes from the associated object trying to find the main record through the id column instead of the configured primary_key. For example, if we have:

class Book < ApplicationRecord
  validates :identifier, presence: true, uniqueness: true
  has_many :reviews, dependent: :destroy
end

# == Schema Information
#
# Table name: books
#
#  id         :bigint(8)        not null, primary key
#  identifier :bigint(8)        not null
#  created_at :datetime         not null
#  updated_at :datetime         not null
#
# Indexes
#
#  index_books_on_identifier  (identifier) UNIQUE
#

class Review < ApplicationRecord
  belongs_to :book, primary_key: :identifier
end

# == Schema Information
#
# Table name: reviews
#
#  id         :bigint(8)        not null, primary key
#  book_id    :bigint(8)        not null
#  created_at :datetime         not null
#  updated_at :datetime         not null
#
# Indexes
#
#  index_reviews_on_book_id  (book_id) UNIQUE
#
# Foreign Keys
#
#  fk_rails_...  (book_id => books.identifier) ON DELETE => cascade
#

And then we do the following:

book = Book.new(identifier: 123456789)
book.reviews.new
Book.import!([book], recursive: true)

It results in a foreign key error, where it tries to insert the book.id in the review.book_id column instead of using book.identifier

  Book Create Many (2.6ms)  INSERT INTO "books" ("id","identifier","created_at","updated_at") VALUES (nextval('public.books_id_seq'),123456789,'2025-07-15 16:53:50.766835','2025-07-15 16:53:50.766835') RETURNING "id"
  Review Create Many (1.3ms)  INSERT INTO "reviews" ("id","book_id","created_at","updated_at") VALUES (nextval('public.reviews_id_seq'),3,'2025-07-15 16:53:50.771991','2025-07-15 16:53:50.771991') RETURNING "id"
ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation: ERROR:  insert or update on table "reviews" violates foreign key constraint "fk_rails_924a0b30ca"
DETAIL:  Key (book_id)=(3) is not present in table "books".

from /Users/my.user/.rbenv/versions/3.1.4/lib/ruby/gems/3.1.0/gems/activerecord-6.1.6/lib/active_record/connection_adapters/postgresql_adapter.rb:672:in `exec_params'
Caused by PG::ForeignKeyViolation: ERROR:  insert or update on table "reviews" violates foreign key constraint "fk_rails_924a0b30ca"
DETAIL:  Key (book_id)=(3) is not present in table "books".

Possible origin and solution

I think the problem originates in this line:

def find_associated_objects_for_import(associated_objects_by_class, model)
	#...
	child.public_send("#{column}=", Array(model.id)[index])
	#...
end

Specifically, the use of model.id directly. I could be wrong, but I think replacing that with model.send(association_reflection.inverse_of.association_primary_key) would fix the issue. At least I did quick test overriding the method and it seems to work.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions