diff --git a/activerecord/lib/active_record/insert_all.rb b/activerecord/lib/active_record/insert_all.rb index fbdb67becb..fa88784e47 100644 --- a/activerecord/lib/active_record/insert_all.rb +++ b/activerecord/lib/active_record/insert_all.rb @@ -14,7 +14,7 @@ module ActiveRecord @returning = (connection.supports_insert_returning? ? primary_keys : false) if @returning.nil? @returning = false if @returning == [] - @unique_by = find_unique_index_for(unique_by || model.primary_key) + @unique_by = find_unique_index_for(unique_by) @on_duplicate = :skip if @on_duplicate == :update && updatable_columns.empty? ensure_valid_options_for_connection! @@ -57,14 +57,15 @@ module ActiveRecord private def find_unique_index_for(unique_by) - match = Array(unique_by).map(&:to_s) + name_or_columns = unique_by || model.primary_key + match = Array(name_or_columns).map(&:to_s) if index = unique_indexes.find { |i| match.include?(i.name) || i.columns == match } index elsif match == primary_keys - nil + unique_by.nil? ? nil : ActiveRecord::ConnectionAdapters::IndexDefinition.new(model.table_name, "#{model.table_name}_primary_key", true, match) else - raise ArgumentError, "No unique index found for #{unique_by}" + raise ArgumentError, "No unique index found for #{name_or_columns}" end end diff --git a/activerecord/test/cases/insert_all_test.rb b/activerecord/test/cases/insert_all_test.rb index 294d40de1e..08ab0ae06b 100644 --- a/activerecord/test/cases/insert_all_test.rb +++ b/activerecord/test/cases/insert_all_test.rb @@ -155,10 +155,11 @@ class InsertAllTest < ActiveRecord::TestCase def test_insert_all_and_upsert_all_with_index_finding_options skip unless supports_insert_conflict_target? - assert_difference "Book.count", +3 do + assert_difference "Book.count", +4 do Book.insert_all [{ name: "Rework", author_id: 1 }], unique_by: :isbn Book.insert_all [{ name: "Remote", author_id: 1 }], unique_by: %i( author_id name ) Book.insert_all [{ name: "Renote", author_id: 1 }], unique_by: :index_books_on_isbn + Book.insert_all [{ name: "Recoat", author_id: 1 }], unique_by: :id end assert_raise ActiveRecord::RecordNotUnique do @@ -227,7 +228,7 @@ class InsertAllTest < ActiveRecord::TestCase end def test_upsert_all_updates_existing_record_by_primary_key - skip unless supports_insert_on_duplicate_update? + skip unless supports_insert_conflict_target? Book.upsert_all [{ id: 1, name: "New edition" }], unique_by: :id