attrocity 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/.gitignore +30 -10
 - data/.rspec +2 -0
 - data/.travis.yml +4 -0
 - data/Gemfile.lock +37 -0
 - data/LICENSE +22 -0
 - data/README.md +32 -2
 - data/Rakefile +14 -0
 - data/TODO.md +36 -0
 - data/attrocity.gemspec +5 -2
 - data/lib/attrocity.rb +91 -2
 - data/lib/attrocity/attributes/attribute.rb +10 -0
 - data/lib/attrocity/attributes/attribute_methods_builder.rb +47 -0
 - data/lib/attrocity/attributes/attribute_set.rb +24 -0
 - data/lib/attrocity/attributes/attribute_template.rb +28 -0
 - data/lib/attrocity/attributes/attribute_template_set.rb +16 -0
 - data/lib/attrocity/attributes/attributes_hash.rb +9 -0
 - data/lib/attrocity/attributes/model_attribute.rb +14 -0
 - data/lib/attrocity/attributes/model_attribute_set.rb +6 -0
 - data/lib/attrocity/builders/model_builder.rb +60 -0
 - data/lib/attrocity/builders/object_extension_builder.rb +18 -0
 - data/lib/attrocity/coercer_registry.rb +38 -0
 - data/lib/attrocity/coercers/boolean.rb +12 -0
 - data/lib/attrocity/coercers/integer.rb +13 -0
 - data/lib/attrocity/coercers/string.rb +14 -0
 - data/lib/attrocity/mappers/key_mapper.rb +14 -0
 - data/lib/attrocity/model.rb +10 -0
 - data/lib/attrocity/value_extractor.rb +23 -0
 - data/lib/attrocity/version.rb +1 -1
 - data/notes.md +253 -0
 - data/spec/attrocity/attributes/attribute_methods_builder_spec.rb +57 -0
 - data/spec/attrocity/attributes/attribute_set_spec.rb +24 -0
 - data/spec/attrocity/attributes/attribute_spec.rb +4 -0
 - data/spec/attrocity/attributes/attribute_template_set_spec.rb +6 -0
 - data/spec/attrocity/attributes/attribute_template_spec.rb +25 -0
 - data/spec/attrocity/attributes/model_attribute_spec.rb +26 -0
 - data/spec/attrocity/attrocity_spec.rb +83 -0
 - data/spec/attrocity/coercer_registry_spec.rb +14 -0
 - data/spec/attrocity/coercers/boolean_spec.rb +32 -0
 - data/spec/attrocity/coercers/coercer_with_args_spec.rb +9 -0
 - data/spec/attrocity/coercers/integer_spec.rb +25 -0
 - data/spec/attrocity/coercers/string_spec.rb +13 -0
 - data/spec/attrocity/default_value_spec.rb +22 -0
 - data/spec/attrocity/mappers/key_mapper_spec.rb +22 -0
 - data/spec/attrocity/mapping_spec.rb +47 -0
 - data/spec/attrocity/model_spec.rb +34 -0
 - data/spec/attrocity/object_extension_spec.rb +53 -0
 - data/spec/attrocity/value_extractor_spec.rb +23 -0
 - data/spec/spec_helper.rb +93 -0
 - data/spec/support/examples.rb +79 -0
 - metadata +99 -8
 
| 
         @@ -0,0 +1,57 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Attrocity
         
     | 
| 
      
 4 
     | 
    
         
            +
              describe AttributeMethodsBuilder do
         
     | 
| 
      
 5 
     | 
    
         
            +
                let(:object) { Object.new }
         
     | 
| 
      
 6 
     | 
    
         
            +
                let(:attr_name) { :a_string }
         
     | 
| 
      
 7 
     | 
    
         
            +
                let(:attribute) { Attribute.new(attr_name, 'hello') }
         
     | 
| 
      
 8 
     | 
    
         
            +
                subject { described_class.new(object, Array(attribute)) }
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                describe '#define_reader' do
         
     | 
| 
      
 11 
     | 
    
         
            +
                  it 'defines a reader method for the attribute' do
         
     | 
| 
      
 12 
     | 
    
         
            +
                    expect {
         
     | 
| 
      
 13 
     | 
    
         
            +
                      subject.define_reader(attribute)
         
     | 
| 
      
 14 
     | 
    
         
            +
                    }.to change { object.respond_to?(attr_name) }.from(false).to(true)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  it 'returns the attribute value from the defined reader method' do
         
     | 
| 
      
 18 
     | 
    
         
            +
                    subject.define_reader(attribute)
         
     | 
| 
      
 19 
     | 
    
         
            +
                    expect(object.send(attr_name)).to eq('hello')
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                describe '#define_writer' do
         
     | 
| 
      
 24 
     | 
    
         
            +
                  it 'defines a writer method for the attribute' do
         
     | 
| 
      
 25 
     | 
    
         
            +
                    expect {
         
     | 
| 
      
 26 
     | 
    
         
            +
                      subject.define_writer(attribute)
         
     | 
| 
      
 27 
     | 
    
         
            +
                    }.to change { object.respond_to?("#{attr_name}=") }.from(false).to(true)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  it 'sets the attribute value' do
         
     | 
| 
      
 31 
     | 
    
         
            +
                    subject.define_writer(attribute)
         
     | 
| 
      
 32 
     | 
    
         
            +
                    object.send("#{attr_name}=", 'foobar')
         
     | 
| 
      
 33 
     | 
    
         
            +
                    expect(attribute.value).to eq('foobar')
         
     | 
| 
      
 34 
     | 
    
         
            +
                  end
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                describe '#define_predicate' do
         
     | 
| 
      
 38 
     | 
    
         
            +
                  it 'defines a predicate method for the attribute' do
         
     | 
| 
      
 39 
     | 
    
         
            +
                    expect {
         
     | 
| 
      
 40 
     | 
    
         
            +
                      subject.define_predicate(attribute)
         
     | 
| 
      
 41 
     | 
    
         
            +
                    }.to change { object.respond_to?("#{attr_name}?") }.from(false).to(true)
         
     | 
| 
      
 42 
     | 
    
         
            +
                  end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                  it 'returns true if the attribute has a truthy value' do
         
     | 
| 
      
 45 
     | 
    
         
            +
                    subject.define_predicate(attribute)
         
     | 
| 
      
 46 
     | 
    
         
            +
                    attribute.value = 'xyz'
         
     | 
| 
      
 47 
     | 
    
         
            +
                    expect(object.send("#{attr_name}?")).to be true
         
     | 
| 
      
 48 
     | 
    
         
            +
                  end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                  it 'returns false if the attribute has a falsy value' do
         
     | 
| 
      
 51 
     | 
    
         
            +
                    subject.define_predicate(attribute)
         
     | 
| 
      
 52 
     | 
    
         
            +
                    expect(attribute).to receive(:value).and_return(nil)
         
     | 
| 
      
 53 
     | 
    
         
            +
                    expect(object.send("#{attr_name}?")).to be false
         
     | 
| 
      
 54 
     | 
    
         
            +
                  end
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
              end
         
     | 
| 
      
 57 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,24 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Attrocity
         
     | 
| 
      
 2 
     | 
    
         
            +
              RSpec.describe AttributeSet do
         
     | 
| 
      
 3 
     | 
    
         
            +
                let(:attrs) { [Attribute.new(:foo, 1), Attribute.new(:bar, 2) ] }
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                subject(:attribute_set) { described_class.new }
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                describe '#<<' do
         
     | 
| 
      
 8 
     | 
    
         
            +
                  it 'adds an attribute' do
         
     | 
| 
      
 9 
     | 
    
         
            +
                    attr = attrs.first
         
     | 
| 
      
 10 
     | 
    
         
            +
                    subject << attr
         
     | 
| 
      
 11 
     | 
    
         
            +
                    expect(attribute_set.attributes).to include(attr)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  it 'raises error when non-attribute is added'
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                describe '#to_h' do
         
     | 
| 
      
 18 
     | 
    
         
            +
                  it 'returns hash of instance attribute names and values' do
         
     | 
| 
      
 19 
     | 
    
         
            +
                    attrs.each { |attr| attribute_set << attr }
         
     | 
| 
      
 20 
     | 
    
         
            +
                    expect(attribute_set.to_h).to eq({ foo: 1, bar: 2 })
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'attrocity/attributes/attribute_template'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Attrocity
         
     | 
| 
      
 4 
     | 
    
         
            +
              RSpec.describe AttributeTemplate do
         
     | 
| 
      
 5 
     | 
    
         
            +
                describe '#mapper_key_for' do
         
     | 
| 
      
 6 
     | 
    
         
            +
                  it "returns mapper key when attribute name matches" do
         
     | 
| 
      
 7 
     | 
    
         
            +
                    attribute = AttributeTemplate.new(
         
     | 
| 
      
 8 
     | 
    
         
            +
                      :street, Coercers::String.new, KeyMapper.new(:addressline1))
         
     | 
| 
      
 9 
     | 
    
         
            +
                    expect(attribute.mapper_key_for(:street)).to eq(:addressline1)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  it "returns mapper key when mapper matches" do
         
     | 
| 
      
 13 
     | 
    
         
            +
                    attribute = AttributeTemplate.new(
         
     | 
| 
      
 14 
     | 
    
         
            +
                      :zip, Coercers::String.new, KeyMapper.new(:zipcode))
         
     | 
| 
      
 15 
     | 
    
         
            +
                    expect(attribute.mapper_key_for(:zipcode)).to eq(:zipcode)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  it 'returns nil when no match' do
         
     | 
| 
      
 19 
     | 
    
         
            +
                    attribute = AttributeTemplate.new(
         
     | 
| 
      
 20 
     | 
    
         
            +
                      :street, Coercers::String.new, KeyMapper.new(:addressline1))
         
     | 
| 
      
 21 
     | 
    
         
            +
                    expect(attribute.mapper_key_for(:nomatch)).to be_nil
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,26 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Attrocity
         
     | 
| 
      
 2 
     | 
    
         
            +
              RSpec.describe ModelAttribute do
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                  let(:listing) {
         
     | 
| 
      
 5 
     | 
    
         
            +
                    Examples::Listing.new({ 'listingid' => '1234',
         
     | 
| 
      
 6 
     | 
    
         
            +
                                            'addressline1' => '100 Elm Street',
         
     | 
| 
      
 7 
     | 
    
         
            +
                                            'zip' => '27571' })
         
     | 
| 
      
 8 
     | 
    
         
            +
                  }
         
     | 
| 
      
 9 
     | 
    
         
            +
                  let(:address) { listing.address }
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  it 'instantiates composed model object' do
         
     | 
| 
      
 12 
     | 
    
         
            +
                    expect(address.street).to eq('100 Elm Street')
         
     | 
| 
      
 13 
     | 
    
         
            +
                    expect(address.zip).to eq('27571')
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  it 'provides model object' do
         
     | 
| 
      
 17 
     | 
    
         
            +
                    model_attr = ModelAttribute.new(:address, Examples::Address)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    address = model_attr.model(
         
     | 
| 
      
 19 
     | 
    
         
            +
                      { 'addressline1' => '100 Elm Street',
         
     | 
| 
      
 20 
     | 
    
         
            +
                        'zip' => '27571' })
         
     | 
| 
      
 21 
     | 
    
         
            +
                    expect(address.street).to eq('100 Elm Street')
         
     | 
| 
      
 22 
     | 
    
         
            +
                    expect(address.zip).to eq('27571')
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,83 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'attrocity'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'support/examples'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module Attrocity
         
     | 
| 
      
 5 
     | 
    
         
            +
              RSpec.describe 'Attrocity module' do
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                describe '.initialize' do
         
     | 
| 
      
 8 
     | 
    
         
            +
                  it 'accepts a hash' do
         
     | 
| 
      
 9 
     | 
    
         
            +
                    expect {
         
     | 
| 
      
 10 
     | 
    
         
            +
                      Examples::Person.new(age: 29)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    }.not_to raise_error
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  let(:person) { Examples::Person.new(age: 29) }
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  it 'creates a reader for instance-scope attribute set' do
         
     | 
| 
      
 17 
     | 
    
         
            +
                    expect { person.attribute_set }.not_to raise_error
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  it 'creates a reader for attribute' do
         
     | 
| 
      
 21 
     | 
    
         
            +
                    expect(person.respond_to?(:age)).to be true
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  # TODO: Move this spec to another unit?
         
     | 
| 
      
 25 
     | 
    
         
            +
                  it 'returns correct value for reader method' do
         
     | 
| 
      
 26 
     | 
    
         
            +
                    expect(person.age).to eq(29)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                describe '.attribute' do
         
     | 
| 
      
 31 
     | 
    
         
            +
                  it 'does not raise error with declarative attribute method' do
         
     | 
| 
      
 32 
     | 
    
         
            +
                    expect {
         
     | 
| 
      
 33 
     | 
    
         
            +
                      module Examples
         
     | 
| 
      
 34 
     | 
    
         
            +
                        class SpecialPerson
         
     | 
| 
      
 35 
     | 
    
         
            +
                          include Attrocity.model
         
     | 
| 
      
 36 
     | 
    
         
            +
                          attribute :foo, coercer: :integer
         
     | 
| 
      
 37 
     | 
    
         
            +
                        end
         
     | 
| 
      
 38 
     | 
    
         
            +
                      end
         
     | 
| 
      
 39 
     | 
    
         
            +
                    }.not_to raise_error
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                  it 'raises error when missing coercer keyword argument' do
         
     | 
| 
      
 43 
     | 
    
         
            +
                    expect {
         
     | 
| 
      
 44 
     | 
    
         
            +
                      module Examples
         
     | 
| 
      
 45 
     | 
    
         
            +
                        class SpecialDog
         
     | 
| 
      
 46 
     | 
    
         
            +
                          include Attrocity.model
         
     | 
| 
      
 47 
     | 
    
         
            +
                          attribute :name
         
     | 
| 
      
 48 
     | 
    
         
            +
                        end
         
     | 
| 
      
 49 
     | 
    
         
            +
                      end
         
     | 
| 
      
 50 
     | 
    
         
            +
                    }.to raise_error(ArgumentError)
         
     | 
| 
      
 51 
     | 
    
         
            +
                  end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                  it 'raises error when using coercer name that is not on the registry' do
         
     | 
| 
      
 54 
     | 
    
         
            +
                    expect {
         
     | 
| 
      
 55 
     | 
    
         
            +
                      module Examples
         
     | 
| 
      
 56 
     | 
    
         
            +
                        class Person
         
     | 
| 
      
 57 
     | 
    
         
            +
                          include Attrocity.model
         
     | 
| 
      
 58 
     | 
    
         
            +
                          attribute :foo, coercer: :xyz
         
     | 
| 
      
 59 
     | 
    
         
            +
                        end
         
     | 
| 
      
 60 
     | 
    
         
            +
                      end
         
     | 
| 
      
 61 
     | 
    
         
            +
                    }.to raise_error(UnknownCoercerError)
         
     | 
| 
      
 62 
     | 
    
         
            +
                  end
         
     | 
| 
      
 63 
     | 
    
         
            +
                end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                describe '#attribute_set' do
         
     | 
| 
      
 66 
     | 
    
         
            +
                  it 'contains expected attributes' do
         
     | 
| 
      
 67 
     | 
    
         
            +
                    pending
         
     | 
| 
      
 68 
     | 
    
         
            +
                    obj = Examples::Person.new(age: 29)
         
     | 
| 
      
 69 
     | 
    
         
            +
                    attribute_names = obj.attribute_set.map(&:name)
         
     | 
| 
      
 70 
     | 
    
         
            +
                    expect(attribute_names).to include(:age)
         
     | 
| 
      
 71 
     | 
    
         
            +
                  end
         
     | 
| 
      
 72 
     | 
    
         
            +
                end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                describe '.model_from_mapped_data' do
         
     | 
| 
      
 75 
     | 
    
         
            +
                  it 'returns an instantiated model' do
         
     | 
| 
      
 76 
     | 
    
         
            +
                    data = { street: '1234 Elm', zip: '27517' }
         
     | 
| 
      
 77 
     | 
    
         
            +
                    address = Examples::Address.model_from_mapped_data(data)
         
     | 
| 
      
 78 
     | 
    
         
            +
                    expect(address.street).to eq('1234 Elm')
         
     | 
| 
      
 79 
     | 
    
         
            +
                    expect(address.zip).to eq('27517')
         
     | 
| 
      
 80 
     | 
    
         
            +
                  end
         
     | 
| 
      
 81 
     | 
    
         
            +
                end
         
     | 
| 
      
 82 
     | 
    
         
            +
              end
         
     | 
| 
      
 83 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'attrocity/coercer_registry'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'support/examples'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module Attrocity
         
     | 
| 
      
 5 
     | 
    
         
            +
              RSpec.describe CoercerRegistry do
         
     | 
| 
      
 6 
     | 
    
         
            +
                it 'adds to the registry' do
         
     | 
| 
      
 7 
     | 
    
         
            +
                  CoercerRegistry.register do
         
     | 
| 
      
 8 
     | 
    
         
            +
                    add :example, Examples::ExampleCoercer
         
     | 
| 
      
 9 
     | 
    
         
            +
                  end
         
     | 
| 
      
 10 
     | 
    
         
            +
                  expect(CoercerRegistry.coercer_for(:example)).
         
     | 
| 
      
 11 
     | 
    
         
            +
                    to eq(Examples::ExampleCoercer)
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,32 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'attrocity/coercers/boolean'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Attrocity
         
     | 
| 
      
 4 
     | 
    
         
            +
              RSpec.describe Coercers::Boolean do
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                subject(:coercer) { Coercers::Boolean.new }
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                describe '#coerce' do
         
     | 
| 
      
 9 
     | 
    
         
            +
                  it 'coerces nil to false' do
         
     | 
| 
      
 10 
     | 
    
         
            +
                    expect(coercer.coerce(nil)).to be false
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  it 'coerces false to false' do
         
     | 
| 
      
 14 
     | 
    
         
            +
                    expect(coercer.coerce(false)).to be false
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  it 'coerces true to true' do
         
     | 
| 
      
 18 
     | 
    
         
            +
                    expect(coercer.coerce(true)).to be true
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  it 'coerces 0 to true' do
         
     | 
| 
      
 22 
     | 
    
         
            +
                    expect(coercer.coerce(0)).to be true
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  it 'coerces an object to true' do
         
     | 
| 
      
 26 
     | 
    
         
            +
                    expect(coercer.coerce(Object.new)).to be true
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
              end
         
     | 
| 
      
 31 
     | 
    
         
            +
            end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'attrocity/coercers/integer'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Attrocity
         
     | 
| 
      
 4 
     | 
    
         
            +
              RSpec.describe Coercers::Integer do
         
     | 
| 
      
 5 
     | 
    
         
            +
                subject(:coercer) { Coercers::Integer.new }
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                describe '#coerce' do
         
     | 
| 
      
 8 
     | 
    
         
            +
                  it 'coerces to an integer' do
         
     | 
| 
      
 9 
     | 
    
         
            +
                    expect(coercer.coerce('1')).to eq(1)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  describe 'given nil' do
         
     | 
| 
      
 13 
     | 
    
         
            +
                    it 'returns nil' do
         
     | 
| 
      
 14 
     | 
    
         
            +
                      expect(coercer.coerce(nil)).to be_nil
         
     | 
| 
      
 15 
     | 
    
         
            +
                    end
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  describe 'given an empty string' do
         
     | 
| 
      
 19 
     | 
    
         
            +
                    it 'returns nil' do
         
     | 
| 
      
 20 
     | 
    
         
            +
                      expect(coercer.coerce('')).to be_nil
         
     | 
| 
      
 21 
     | 
    
         
            +
                    end
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Attrocity
         
     | 
| 
      
 2 
     | 
    
         
            +
              RSpec.describe 'Default value' do
         
     | 
| 
      
 3 
     | 
    
         
            +
                before do
         
     | 
| 
      
 4 
     | 
    
         
            +
                  module Examples
         
     | 
| 
      
 5 
     | 
    
         
            +
                    class DefaultValueExample
         
     | 
| 
      
 6 
     | 
    
         
            +
                      include Attrocity.model
         
     | 
| 
      
 7 
     | 
    
         
            +
                      attribute :bool, coercer: :boolean, default: true
         
     | 
| 
      
 8 
     | 
    
         
            +
                    end
         
     | 
| 
      
 9 
     | 
    
         
            +
                  end
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                it 'defaults to default value' do
         
     | 
| 
      
 13 
     | 
    
         
            +
                  example = Examples::DefaultValueExample.new
         
     | 
| 
      
 14 
     | 
    
         
            +
                  expect(example.bool).to be true
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                it 'overrides default value' do
         
     | 
| 
      
 18 
     | 
    
         
            +
                  example = Examples::DefaultValueExample.new(bool: false)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  expect(example.bool).to be false
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Attrocity
         
     | 
| 
      
 2 
     | 
    
         
            +
              RSpec.describe KeyMapper do
         
     | 
| 
      
 3 
     | 
    
         
            +
                let(:default_value) { nil }
         
     | 
| 
      
 4 
     | 
    
         
            +
                subject(:mapper) { KeyMapper.new(:foo, default_value) }
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                it 'extracts data via hash key' do
         
     | 
| 
      
 7 
     | 
    
         
            +
                  expect(mapper.call(double, { foo: 'bar' })).to eq('bar')
         
     | 
| 
      
 8 
     | 
    
         
            +
                end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                it 'returns default value when key absent' do
         
     | 
| 
      
 11 
     | 
    
         
            +
                  expect(mapper.call(double, { biz: 'baz' })).to eq(default_value)
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                describe 'override default value' do
         
     | 
| 
      
 15 
     | 
    
         
            +
                  let(:default_value) { true }
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  it 'returns overridden value when key is absent' do
         
     | 
| 
      
 18 
     | 
    
         
            +
                    expect(mapper.call(double, { biz: 'baz' })).to eq(default_value)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,47 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'support/examples'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'attrocity'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module Attrocity
         
     | 
| 
      
 5 
     | 
    
         
            +
              RSpec.describe "Mapping" do
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                describe 'with default key mapper' do
         
     | 
| 
      
 8 
     | 
    
         
            +
                  let(:data) { { 'listingid' => '1234' } }
         
     | 
| 
      
 9 
     | 
    
         
            +
                  let(:listing) { Examples::Listing.new(data) }
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  it 'maps attribute data to attribute name' do
         
     | 
| 
      
 12 
     | 
    
         
            +
                    expect(listing.id).to eq('1234')
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  it 'does not respond to mapped name' do
         
     | 
| 
      
 16 
     | 
    
         
            +
                    expect { listing.listingid }.to raise_error(NoMethodError)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                describe 'with proc mapper' do
         
     | 
| 
      
 21 
     | 
    
         
            +
                  before do
         
     | 
| 
      
 22 
     | 
    
         
            +
                    module Examples
         
     | 
| 
      
 23 
     | 
    
         
            +
                      class WithProcMapper
         
     | 
| 
      
 24 
     | 
    
         
            +
                        include Attrocity.model
         
     | 
| 
      
 25 
     | 
    
         
            +
                        attribute :age,
         
     | 
| 
      
 26 
     | 
    
         
            +
                          coercer: :integer,
         
     | 
| 
      
 27 
     | 
    
         
            +
                          from: lambda { |obj, attrs_data| attrs_data['properties']['age'] }
         
     | 
| 
      
 28 
     | 
    
         
            +
                      end
         
     | 
| 
      
 29 
     | 
    
         
            +
                    end
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                  it 'maps attribute data to attribute name' do
         
     | 
| 
      
 33 
     | 
    
         
            +
                    object = Examples::WithProcMapper.new({'properties' => { 'age' => 27 } })
         
     | 
| 
      
 34 
     | 
    
         
            +
                    expect(object.age).to eq(27)
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                describe 'without explicit mapper' do
         
     | 
| 
      
 40 
     | 
    
         
            +
                  it 'maps attribute data to attribute name' do
         
     | 
| 
      
 41 
     | 
    
         
            +
                    person = Examples::Person.new(age: 44)
         
     | 
| 
      
 42 
     | 
    
         
            +
                    expect(person.age).to eq(44)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
              end
         
     | 
| 
      
 47 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,34 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Attrocity
         
     | 
| 
      
 2 
     | 
    
         
            +
              RSpec.describe 'Attrocity.model' do
         
     | 
| 
      
 3 
     | 
    
         
            +
                describe '#model' do
         
     | 
| 
      
 4 
     | 
    
         
            +
                  let(:person) { Examples::Person.new(age: 50) }
         
     | 
| 
      
 5 
     | 
    
         
            +
                  let(:model) { person.model }
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  it 'responds to a reader' do
         
     | 
| 
      
 8 
     | 
    
         
            +
                    expect(model.respond_to?(:age)).to be true
         
     | 
| 
      
 9 
     | 
    
         
            +
                  end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  it 'does not respond to a writer' do
         
     | 
| 
      
 12 
     | 
    
         
            +
                    expect(model.respond_to?(:age=)).to be false
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  it 'responds to predicate'do
         
     | 
| 
      
 16 
     | 
    
         
            +
                    expect(model.respond_to?(:age?)).to be true
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  it 'has correct value for attribute' do
         
     | 
| 
      
 20 
     | 
    
         
            +
                    expect(model.age).to eq(50)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  it 'has correct value for predicate' do
         
     | 
| 
      
 24 
     | 
    
         
            +
                    expect(model.age?).to be true
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  it 'includes model attributes' do
         
     | 
| 
      
 28 
     | 
    
         
            +
                    listing = Examples::Listing.new({ id: '1234', zip: '10101' })
         
     | 
| 
      
 29 
     | 
    
         
            +
                    model = listing.model
         
     | 
| 
      
 30 
     | 
    
         
            +
                    expect(model.address).not_to be_nil
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
            end
         
     |