aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/cases/insert_all_test.rb
diff options
context:
space:
mode:
authorKasper Timm Hansen <kaspth@gmail.com>2019-03-09 01:15:17 +0100
committerKasper Timm Hansen <kaspth@gmail.com>2019-03-20 13:28:18 +0100
commit2ea5c24085e39efb6c1bc6e7062bcc5f496d1fa6 (patch)
tree9a6448dca6dcd973957584686edf60961189ae01 /activerecord/test/cases/insert_all_test.rb
parentc11d115fa3c58ec6bde5e9799673cee381d22d47 (diff)
downloadrails-2ea5c24085e39efb6c1bc6e7062bcc5f496d1fa6.tar.gz
rails-2ea5c24085e39efb6c1bc6e7062bcc5f496d1fa6.tar.bz2
rails-2ea5c24085e39efb6c1bc6e7062bcc5f496d1fa6.zip
Bulk Insert: Reuse indexes for unique_by
I found `:unique_by` with `:columns` and `:where` inside it tough to grasp. The documentation only mentioned indexes and partial indexes. So why duplicate a model's indexes in an insert_all/upsert_all call when we can just look it up? This has the added benefit of raising if no index is found, such that people can't insert thousands of records without relying on an index of some form.
Diffstat (limited to 'activerecord/test/cases/insert_all_test.rb')
-rw-r--r--activerecord/test/cases/insert_all_test.rb36
1 files changed, 33 insertions, 3 deletions
diff --git a/activerecord/test/cases/insert_all_test.rb b/activerecord/test/cases/insert_all_test.rb
index a3e920969d..0818d7c1ab 100644
--- a/activerecord/test/cases/insert_all_test.rb
+++ b/activerecord/test/cases/insert_all_test.rb
@@ -95,7 +95,37 @@ class InsertAllTest < ActiveRecord::TestCase
assert_raise ActiveRecord::RecordNotUnique do
Book.insert_all [{ id: 1, name: "Agile Web Development with Rails" }],
- unique_by: { columns: %i{author_id name} }
+ unique_by: :index_books_on_author_id_and_name
+ end
+ end
+
+ def test_insert_all_and_upsert_all_with_index_finding_options
+ skip unless supports_insert_conflict_target?
+
+ assert_difference "Book.count", +3 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
+ end
+
+ assert_raise ActiveRecord::RecordNotUnique do
+ Book.upsert_all [{ name: "Rework", author_id: 1 }], unique_by: :isbn
+ end
+ end
+
+ def test_insert_all_and_upsert_all_raises_when_index_is_missing
+ skip unless supports_insert_conflict_target?
+
+ [ :cats, %i( author_id isbn ), :author_id ].each do |missing_or_non_unique_by|
+ error = assert_raises ArgumentError do
+ Book.insert_all [{ name: "Rework", author_id: 1 }], unique_by: missing_or_non_unique_by
+ end
+ assert_match "No unique index", error.message
+
+ error = assert_raises ArgumentError do
+ Book.upsert_all [{ name: "Rework", author_id: 1 }], unique_by: missing_or_non_unique_by
+ end
+ assert_match "No unique index", error.message
end
end
@@ -120,7 +150,7 @@ class InsertAllTest < ActiveRecord::TestCase
Book.upsert_all [{ id: 101, name: "Perelandra", author_id: 7 }]
Book.upsert_all [{ id: 103, name: "Perelandra", author_id: 7, isbn: "1974522598" }],
- unique_by: { columns: %i{author_id name} }
+ unique_by: :index_books_on_author_id_and_name
book = Book.find_by(name: "Perelandra")
assert_equal 101, book.id, "Should not have updated the ID"
@@ -132,7 +162,7 @@ class InsertAllTest < ActiveRecord::TestCase
Book.upsert_all [{ name: "Out of the Silent Planet", author_id: 7, isbn: "1974522598", published_on: Date.new(1938, 4, 1) }]
Book.upsert_all [{ name: "Perelandra", author_id: 7, isbn: "1974522598" }],
- unique_by: { columns: %w[ isbn ], where: "published_on IS NOT NULL" }
+ unique_by: :index_books_on_isbn
assert_equal ["Out of the Silent Planet", "Perelandra"], Book.where(isbn: "1974522598").order(:name).pluck(:name)
end