summaryrefslogtreecommitdiff
path: root/spec/models/concerns/bulk_insert_safe_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/models/concerns/bulk_insert_safe_spec.rb')
-rw-r--r--spec/models/concerns/bulk_insert_safe_spec.rb179
1 files changed, 92 insertions, 87 deletions
diff --git a/spec/models/concerns/bulk_insert_safe_spec.rb b/spec/models/concerns/bulk_insert_safe_spec.rb
index 07d6cee487f..82b0c00b396 100644
--- a/spec/models/concerns/bulk_insert_safe_spec.rb
+++ b/spec/models/concerns/bulk_insert_safe_spec.rb
@@ -2,57 +2,7 @@
require 'spec_helper'
-describe BulkInsertSafe do
- class BulkInsertItem < ActiveRecord::Base
- include BulkInsertSafe
- include ShaAttribute
-
- validates :name, :enum_value, :secret_value, :sha_value, :jsonb_value, presence: true
-
- ENUM_VALUES = {
- case_1: 1
- }.freeze
-
- sha_attribute :sha_value
-
- enum enum_value: ENUM_VALUES
-
- attr_encrypted :secret_value,
- mode: :per_attribute_iv,
- algorithm: 'aes-256-gcm',
- key: Settings.attr_encrypted_db_key_base_32,
- insecure_mode: false
-
- default_value_for :enum_value, 'case_1'
- default_value_for :secret_value, 'my-secret'
- default_value_for :sha_value, '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12'
- default_value_for :jsonb_value, { "key" => "value" }
-
- def self.valid_list(count)
- Array.new(count) { |n| new(name: "item-#{n}") }
- end
-
- def self.invalid_list(count)
- Array.new(count) { new }
- end
- end
-
- module InheritedUnsafeMethods
- extend ActiveSupport::Concern
-
- included do
- after_save -> { "unsafe" }
- end
- end
-
- module InheritedSafeMethods
- extend ActiveSupport::Concern
-
- included do
- after_initialize -> { "safe" }
- end
- end
-
+RSpec.describe BulkInsertSafe do
before(:all) do
ActiveRecord::Schema.define do
create_table :bulk_insert_items, force: true do |t|
@@ -66,100 +16,155 @@ describe BulkInsertSafe do
t.index :name, unique: true
end
end
-
- BulkInsertItem.reset_column_information
end
after(:all) do
ActiveRecord::Schema.define do
drop_table :bulk_insert_items, force: true
end
+ end
+
+ let_it_be(:bulk_insert_item_class) do
+ Class.new(ActiveRecord::Base) do
+ self.table_name = 'bulk_insert_items'
- BulkInsertItem.reset_column_information
+ include BulkInsertSafe
+ include ShaAttribute
+
+ validates :name, :enum_value, :secret_value, :sha_value, :jsonb_value, presence: true
+
+ sha_attribute :sha_value
+
+ enum enum_value: { case_1: 1 }
+
+ attr_encrypted :secret_value,
+ mode: :per_attribute_iv,
+ algorithm: 'aes-256-gcm',
+ key: Settings.attr_encrypted_db_key_base_32,
+ insecure_mode: false
+
+ default_value_for :enum_value, 'case_1'
+ default_value_for :secret_value, 'my-secret'
+ default_value_for :sha_value, '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12'
+ default_value_for :jsonb_value, { "key" => "value" }
+
+ def self.name
+ 'BulkInsertItem'
+ end
+
+ def self.valid_list(count)
+ Array.new(count) { |n| new(name: "item-#{n}") }
+ end
+
+ def self.invalid_list(count)
+ Array.new(count) { new }
+ end
+ end
end
- describe BulkInsertItem do
- it_behaves_like 'a BulkInsertSafe model', described_class do
- let(:valid_items_for_bulk_insertion) { described_class.valid_list(10) }
- let(:invalid_items_for_bulk_insertion) { described_class.invalid_list(10) }
+ describe 'BulkInsertItem' do
+ it_behaves_like 'a BulkInsertSafe model' do
+ let(:target_class) { bulk_insert_item_class.dup }
+ let(:valid_items_for_bulk_insertion) { target_class.valid_list(10) }
+ let(:invalid_items_for_bulk_insertion) { target_class.invalid_list(10) }
end
context 'when inheriting class methods' do
+ let(:inherited_unsafe_methods_module) do
+ Module.new do
+ extend ActiveSupport::Concern
+
+ included do
+ after_save -> { "unsafe" }
+ end
+ end
+ end
+
+ let(:inherited_safe_methods_module) do
+ Module.new do
+ extend ActiveSupport::Concern
+
+ included do
+ after_initialize -> { "safe" }
+ end
+ end
+ end
+
it 'raises an error when method is not bulk-insert safe' do
- expect { described_class.include(InheritedUnsafeMethods) }
- .to raise_error(described_class::MethodNotAllowedError)
+ expect { bulk_insert_item_class.include(inherited_unsafe_methods_module) }
+ .to raise_error(bulk_insert_item_class::MethodNotAllowedError)
end
it 'does not raise an error when method is bulk-insert safe' do
- expect { described_class.include(InheritedSafeMethods) }.not_to raise_error
+ expect { bulk_insert_item_class.include(inherited_safe_methods_module) }.not_to raise_error
end
end
context 'primary keys' do
it 'raises error if primary keys are set prior to insertion' do
- item = described_class.new(name: 'valid', id: 10)
+ item = bulk_insert_item_class.new(name: 'valid', id: 10)
- expect { described_class.bulk_insert!([item]) }
- .to raise_error(described_class::PrimaryKeySetError)
+ expect { bulk_insert_item_class.bulk_insert!([item]) }
+ .to raise_error(bulk_insert_item_class::PrimaryKeySetError)
end
end
describe '.bulk_insert!' do
it 'inserts items in the given number of batches' do
- items = described_class.valid_list(10)
+ items = bulk_insert_item_class.valid_list(10)
expect(ActiveRecord::InsertAll).to receive(:new).twice.and_call_original
- described_class.bulk_insert!(items, batch_size: 5)
+ bulk_insert_item_class.bulk_insert!(items, batch_size: 5)
end
it 'items can be properly fetched from database' do
- items = described_class.valid_list(10)
+ items = bulk_insert_item_class.valid_list(10)
- described_class.bulk_insert!(items)
+ bulk_insert_item_class.bulk_insert!(items)
- attribute_names = described_class.attribute_names - %w[id created_at updated_at]
- expect(described_class.last(items.size).pluck(*attribute_names)).to eq(
+ attribute_names = bulk_insert_item_class.attribute_names - %w[id created_at updated_at]
+ expect(bulk_insert_item_class.last(items.size).pluck(*attribute_names)).to eq(
items.pluck(*attribute_names))
end
it 'rolls back the transaction when any item is invalid' do
# second batch is bad
- all_items = described_class.valid_list(10) +
- described_class.invalid_list(10)
+ all_items = bulk_insert_item_class.valid_list(10) +
+ bulk_insert_item_class.invalid_list(10)
expect do
- described_class.bulk_insert!(all_items, batch_size: 2) rescue nil
- end.not_to change { described_class.count }
+ bulk_insert_item_class.bulk_insert!(all_items, batch_size: 2) rescue nil
+ end.not_to change { bulk_insert_item_class.count }
end
it 'does nothing and returns an empty array when items are empty' do
- expect(described_class.bulk_insert!([])).to eq([])
- expect(described_class.count).to eq(0)
+ expect(bulk_insert_item_class.bulk_insert!([])).to eq([])
+ expect(bulk_insert_item_class.count).to eq(0)
end
context 'with returns option set' do
context 'when is set to :ids' do
it 'return an array with the primary key values for all inserted records' do
- items = described_class.valid_list(1)
+ items = bulk_insert_item_class.valid_list(1)
- expect(described_class.bulk_insert!(items, returns: :ids)).to contain_exactly(a_kind_of(Integer))
+ expect(bulk_insert_item_class.bulk_insert!(items, returns: :ids)).to contain_exactly(a_kind_of(Integer))
end
end
context 'when is set to nil' do
it 'returns an empty array' do
- items = described_class.valid_list(1)
+ items = bulk_insert_item_class.valid_list(1)
- expect(described_class.bulk_insert!(items, returns: nil)).to eq([])
+ expect(bulk_insert_item_class.bulk_insert!(items, returns: nil)).to eq([])
end
end
context 'when is set to anything else' do
it 'raises an error' do
- items = described_class.valid_list(1)
+ items = bulk_insert_item_class.valid_list(1)
- expect { described_class.bulk_insert!([items], returns: [:id, :name]) }
+ expect { bulk_insert_item_class.bulk_insert!([items], returns: [:id, :name]) }
.to raise_error(ArgumentError, "returns needs to be :ids or nil")
end
end
@@ -167,20 +172,20 @@ describe BulkInsertSafe do
end
context 'when duplicate items are to be inserted' do
- let!(:existing_object) { described_class.create!(name: 'duplicate', secret_value: 'old value') }
- let(:new_object) { described_class.new(name: 'duplicate', secret_value: 'new value') }
+ let!(:existing_object) { bulk_insert_item_class.create!(name: 'duplicate', secret_value: 'old value') }
+ let(:new_object) { bulk_insert_item_class.new(name: 'duplicate', secret_value: 'new value') }
describe '.bulk_insert!' do
context 'when skip_duplicates is set to false' do
it 'raises an exception' do
- expect { described_class.bulk_insert!([new_object], skip_duplicates: false) }
+ expect { bulk_insert_item_class.bulk_insert!([new_object], skip_duplicates: false) }
.to raise_error(ActiveRecord::RecordNotUnique)
end
end
context 'when skip_duplicates is set to true' do
it 'does not update existing object' do
- described_class.bulk_insert!([new_object], skip_duplicates: true)
+ bulk_insert_item_class.bulk_insert!([new_object], skip_duplicates: true)
expect(existing_object.reload.secret_value).to eq('old value')
end
@@ -189,7 +194,7 @@ describe BulkInsertSafe do
describe '.bulk_upsert!' do
it 'updates existing object' do
- described_class.bulk_upsert!([new_object], unique_by: %w[name])
+ bulk_insert_item_class.bulk_upsert!([new_object], unique_by: %w[name])
expect(existing_object.reload.secret_value).to eq('new value')
end