1
0

Extract default repository behavior into base class

This commit is contained in:
Tim Kächele 2021-03-06 17:32:47 +01:00
parent 66886e6ae6
commit b6f2d46d91
5 changed files with 110 additions and 59 deletions

View File

@ -1,6 +1,9 @@
# frozen_string_literal: true
require 'planet_express/version'
require 'planet_express/repository'
require 'planet_express/shipping_option'
require 'planet_express/shipping_option_repository'

View File

@ -0,0 +1,29 @@
module PlanetExpress
class Repository
attr_reader :data
def initialize(data: )
@data = data
end
def all
data
end
def add(item)
data.push(item)
end
def remove(item)
data.delete(item)
end
def where(attribute_matchers = {})
all.select do |entry|
attribute_matchers.map do |attribute, value|
entry.public_send(attribute.to_sym) == value
end.all?
end
end
end
end

View File

@ -1,24 +1,12 @@
# frozen_string_literal: true
module PlanetExpress
class ShippingOptionRepository
class ShippingOptionRepository < Repository
attr_reader :data
def initialize(data: nil)
@data = data || default_data
end
def all
data
end
def where(attribute_matchers = {})
all.select do |entry|
attribute_matchers.map do |attribute, value|
entry.public_send(attribute.to_sym) == value
end.all?
end
end
def find_by_provider_and_package_size(provider, package_size)
where(provider: provider, package_size: package_size).first
end

77
spec/repository_spec.rb Normal file
View File

@ -0,0 +1,77 @@
# frozen_string_literal: true
RSpec.describe PlanetExpress::Repository do
let!(:repository_item_class) { Struct.new(:test_attribute_a, :test_attribute_b) }
let(:repository_items) do
5.times.map do |i|
repository_item_class.new(i * 100, "Testing #{i}")
end
end
let!(:entries) { repository_items }
subject { described_class.new(data: entries) }
describe '#where' do
context 'no data' do
let(:entries) { [] }
it 'returns an empty array' do
expect(subject.where()).to eq([])
end
end
context 'no arguments' do
before(:each) do
expect(subject.all).to_not be_empty
end
it 'returns all items' do
expect(subject.where()).to eq(subject.all)
end
end
context 'with existing attribute' do
let(:expected_item) do
repository_item_class.new(150, 'Testing')
end
let(:entries) { repository_items + [expected_item] }
it 'returns a list with the expected item' do
expect(subject.where(test_attribute_a: 150, test_attribute_b: "Testing")).to eq([expected_item])
end
end
context 'with unknown attribute' do
it 'throws an exception' do
expect do
subject.where(unknown_attribute: nil)
end.to raise_error(NoMethodError)
end
end
end
describe '#add' do
let(:item) { repository_item_class.new(152, 'Testing') }
it 'adds the item to the list' do
subject.add(item)
expect(subject.where(test_attribute_a: 152, test_attribute_b: 'Testing')).to eq([item])
end
end
describe '#remove' do
let(:item) { repository_item_class.new(153, 'Test') }
it 'removes the item from the list' do
subject.add(item)
expect { subject.remove(item) }
.to(change { subject.where(test_attribute_a: 153, test_attribute_b: 'Test') }.to([]))
end
end
end

View File

@ -3,52 +3,6 @@
RSpec.describe PlanetExpress::ShippingOptionRepository do
subject { PlanetExpress::ShippingOptionRepository.new }
describe '#where' do
context 'no data' do
subject { PlanetExpress::ShippingOptionRepository.new(data: []) }
it 'returns an empty array' do
expect(subject.where()).to eq([])
end
end
context 'no arguments' do
before(:each) do
expect(subject.all).to_not be_empty
end
it 'returns all items' do
expect(subject.where()).to eq(subject.all)
end
end
context 'with existing attribute' do
let(:expected_item) do
build(:shipping_option, package_size: 'L', price_in_cents: 410)
end
let(:data) do
build_list(:shipping_option, 4, price_in_cents: 500) + [expected_item]
end
subject do
PlanetExpress::ShippingOptionRepository.new(data: data)
end
it 'returns a list with the expected item' do
expect(subject.where(package_size: 'L', price_in_cents: 410)).to eq([expected_item])
end
end
context 'with unknown attribute' do
it 'throws an exception' do
expect do
subject.where(unknown_attribute: nil)
end.to raise_error(NoMethodError)
end
end
end
describe '#lowest_price_for_package_size' do
it 'finds the lowest price for a package size' do
expect(subject.lowest_price_for_package_size('L')).to eq(400)