require 'spec_helper' require 'roqua/core_ext/activerecord/uniq_find_or_create' describe ActiveRecord::Base do let(:attributes) { double('attributes') } let(:block) { -> (*args){} } let(:record) { double('record') } describe '#uniq_find_or_create_by' do it 'tries to find or create a record by the attributes provided' do expect(ActiveRecord::Base).to receive(:find_or_create_by).with(attributes, &block).and_return record ActiveRecord::Base.uniq_find_or_create_by attributes, &block end it 'returns a preexisting or created record by querying it' do allow(ActiveRecord::Base).to receive(:find_or_create_by).with(attributes).and_return record expect(ActiveRecord::Base.uniq_find_or_create_by attributes, &block).to eq(record) end it 'returns a concurrenlty created record' do allow(ActiveRecord::Base).to receive(:find_by).with(attributes).and_return record allow(ActiveRecord::Base).to receive(:find_or_create_by).with(attributes, &block) .and_raise ActiveRecord::RecordNotUnique.new('') expect(ActiveRecord::Base.uniq_find_or_create_by attributes, &block).to eq(record) end it 'raises when a concurrent record is detected by the database but could not be queried for unknown reasons' do allow(ActiveRecord::Base).to receive(:find_by).with(attributes).and_return nil allow(ActiveRecord::Base).to receive(:find_or_create_by).with(attributes, &block) .and_raise ActiveRecord::RecordNotUnique.new('') expect do ActiveRecord::Base.uniq_find_or_create_by attributes, &block end.to raise_error ActiveRecord::RecordNotUnique end it 'returns the created record for inspection when validation fails' do allow(ActiveRecord::Base).to receive(:find_or_create_by).with(attributes, &block).and_return record expect(ActiveRecord::Base.uniq_find_or_create_by attributes, &block).to eq(record) end end describe '#uniq_find_or_create_by!' do it 'tries to find or create a record by the attributes provided' do allow(ActiveRecord::Base).to receive(:find_by).with(attributes).and_return record expect(ActiveRecord::Base).to receive(:find_or_create_by!).with(attributes, &block) ActiveRecord::Base.uniq_find_or_create_by! attributes, &block end it 'returns a preexisting or created record by querying it' do allow(ActiveRecord::Base).to receive(:find_or_create_by!).with(attributes).and_return record expect(ActiveRecord::Base.uniq_find_or_create_by! attributes, &block).to eq(record) end it 'returns a concurrenlty created record' do allow(ActiveRecord::Base).to receive(:find_by).with(attributes).and_return record allow(ActiveRecord::Base).to receive(:find_or_create_by!).with(attributes, &block) .and_raise ActiveRecord::RecordNotUnique.new('') expect(ActiveRecord::Base.uniq_find_or_create_by! attributes, &block).to eq(record) end it 'raises when a concurrent record is detected by the database but could not be queried for unknown reasons' do allow(ActiveRecord::Base).to receive(:find_by).with(attributes).and_return nil allow(ActiveRecord::Base).to receive(:find_or_create_by!).with(attributes, &block) .and_raise ActiveRecord::RecordNotUnique.new('') expect do ActiveRecord::Base.uniq_find_or_create_by! attributes, &block end.to raise_error ActiveRecord::RecordNotUnique end it 'raises when creating a new record causes validation failures not due to concurrency' do exception = StandardError.new('some_validation_error') allow(ActiveRecord::Base).to receive(:find_or_create_by!).with(attributes, &block).and_raise exception expect { ActiveRecord::Base.uniq_find_or_create_by! attributes, &block }.to raise_error(exception) end end end