From 1af44e4aeeb04a6360b5104d8ee7b4a042ef93d8 Mon Sep 17 00:00:00 2001 From: Lachlan Sylvester Date: Fri, 21 Jun 2019 15:34:45 +1000 Subject: handle passing in primary key to unique_by, and handle primary keys missing indexes --- activerecord/lib/active_record/insert_all.rb | 6 ++++-- activerecord/test/cases/insert_all_test.rb | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/activerecord/lib/active_record/insert_all.rb b/activerecord/lib/active_record/insert_all.rb index f6577dcbc4..3863b6bfea 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) if unique_by + @unique_by = find_unique_index_for(unique_by || model.primary_key) @on_duplicate = :skip if @on_duplicate == :update && updatable_columns.empty? ensure_valid_options_for_connection! @@ -32,7 +32,7 @@ module ActiveRecord end def primary_keys - Array(model.primary_key) + Array(connection.schema_cache.primary_keys(model.table_name)) end @@ -61,6 +61,8 @@ module ActiveRecord if index = unique_indexes.find { |i| match.include?(i.name) || i.columns == match } index + elsif match == primary_keys + nil else raise ArgumentError, "No unique index found for #{unique_by}" end diff --git a/activerecord/test/cases/insert_all_test.rb b/activerecord/test/cases/insert_all_test.rb index d086d77081..42c623fafb 100644 --- a/activerecord/test/cases/insert_all_test.rb +++ b/activerecord/test/cases/insert_all_test.rb @@ -2,6 +2,7 @@ require "cases/helper" require "models/book" +require "models/speedometer" class ReadonlyNameBook < Book attr_readonly :name @@ -225,6 +226,23 @@ class InsertAllTest < ActiveRecord::TestCase assert_equal new_name, Book.find(1).name end + def test_upsert_all_updates_existing_record_by_primary_key + skip unless supports_insert_on_duplicate_update? + + Book.upsert_all [{ id: 1, name: "New edition" }], unique_by: :id + + assert_equal "New edition", Book.find(1).name + end + + def test_upsert_all_updates_existing_record_by_configured_primary_key + skip unless supports_insert_on_duplicate_update? + + error = assert_raises ArgumentError do + Speedometer.upsert_all [{ speedometer_id: "s1", name: "New Speedometer" }] + end + assert_match "No unique index found for speedometer_id", error.message + end + def test_upsert_all_does_not_update_readonly_attributes skip unless supports_insert_on_duplicate_update? -- cgit v1.2.3