require 'spec_helper' describe Acfs::Model::Attributes do let(:model) { Class.new.tap { |c| c.send :include, Acfs::Model }} describe '#initialize' do before { model.attribute :name, :string, default: 'John' } it 'should have attribute list' do expect(model.new.attributes).to include(:name) end it 'should set default attributes' do expect(model.new.name).to be == 'John' end context 'with dynamic default value' do before do model.attribute :name, :string, default: 'John' model.attribute :mail, :string, default: -> { "#{name}@srv.tld" } end it 'should set dynamic default attributes' do expect(model.new.mail).to be == 'John@srv.tld' end end end describe '#attributes' do before do model.attribute :name, :string, default: 'John' model.attribute :age, :integer, default: 25 end it 'should return hash of all attributes' do expect(model.new.attributes).to be == { name: 'John', age: 25 }.stringify_keys end end describe '#write_attributes' do before do model.attribute :name, :string, default: 'John' model.attribute :age, :integer, default: 25 end let(:args) { [params] } let(:params){ {name: 'James'} } let(:m) { model.new } let(:action) { lambda{ m.write_attributes *args } } subject { action } it 'should update attributes' do should change(m, :attributes) .from({'name' => 'John', 'age' => 25}) .to({'name' => 'James', 'age' => 25}) end context 'without non-hash params' do let(:params) { 'James' } it { should_not change(m, :attributes) } its(:call) { should eq false } end context 'with unknown attributes' do let(:params) { {name: 'James', born_at: Time.now} } it { should_not raise_error } it 'should update known attributes' do should change(m, :attributes) .from({'name' => 'John', 'age' => 25}) .to({'name' => 'James', 'age' => 25}) end context 'with unknown: :raise option' do let(:args) { [params, {unknown: :raise}] } it { should raise_error(ArgumentError, /unknown attribute/i) } it { expect{ subject.call rescue true }.to_not change(m, :attributes) } end end end describe '#_getter_' do before { model.attribute :name, :string, default: 'John' } it 'should return value' do mo = model.new mo.name = 'Paul' expect(mo.name).to be == 'Paul' end it 'should return default value' do expect(model.new.name).to be == 'John' end it 'should return matching ivar\'s value' do o = model.new o.instance_variable_set :@name, 'Johannes' expect(o.name).to be == 'Johannes' end end describe '#_setter_' do before do model.attribute :name, :string, default: 'John' model.attribute :age, :integer, default: '25' end it 'should set value' do o = model.new o.name = 'Paul' expect(o.name).to be == 'Paul' end it 'should set instance var' do o = model.new o.name = 'Paul' expect(o.instance_variable_get(:@name)).to be == 'Paul' end it 'should update attributes hash' do o = model.new o.name = 'Johannes' expect(o.attributes['name']).to be == 'Johannes' end it 'should cast values' do o = model.new o.age = '28' expect(o.age).to be == 28 end end describe 'class' do describe '#attribute' do it 'should add an attribute to model attribute list' do model.send :attribute, :name, :string expect(model.attributes).to be == { :name => nil }.stringify_keys end it 'should accept a default value' do model.send :attribute, :name, :string, default: 'John' expect(model.attributes).to be == { :name => 'John' }.stringify_keys end it 'should accept an symbolic type' do model.send :attribute, :age, :integer, default: '12' expect(model.attributes).to be == { :age => 12 }.stringify_keys end it 'should accept an class type' do model.send :attribute, :age, Acfs::Model::Attributes::Integer, default: '12' expect(model.attributes).to be == { :age => 12 }.stringify_keys end context 'allow nil option' do it 'should allow nil as value' do model.send :attribute, :updated_at, Acfs::Model::Attributes::DateTime, default: DateTime.new, allow_nil: true resource = model.new expect(resource.updated_at).to eq DateTime.new resource.updated_at = '' expect(resource.updated_at).to eq nil end end context 'allow blank option' do it 'should allow blank as value' do model.send :attribute, :updated_at, Acfs::Model::Attributes::DateTime, default: DateTime.new, allow_blank: true resource = model.new expect(resource.updated_at).to eq DateTime.new resource.updated_at = '' expect(resource.updated_at).to eq nil end end end end end