diff --git a/lib/shallow_attributes/class_methods.rb b/lib/shallow_attributes/class_methods.rb index 1353c66..71333a2 100644 --- a/lib/shallow_attributes/class_methods.rb +++ b/lib/shallow_attributes/class_methods.rb @@ -14,6 +14,14 @@ module ClassMethods # def inherited(subclass) super + if respond_to?(:descriptions) + subclass.descriptions.merge!(descriptions) + end + + if respond_to?(:formats) + subclass.formats.merge!(formats) + end + if respond_to?(:default_values) subclass.default_values.merge!(default_values) end @@ -41,6 +49,14 @@ def mandatory_attributes @mandatory_attributes ||= {} end + def descriptions + @descriptions ||= {} + end + + def formats + @formats ||= {} + end + # Returns all class attributes. # # @example Create new User instance @@ -88,6 +104,8 @@ def attribute(name, type, options = {}) default_values[name] = options.delete(:default) mandatory_attributes[name] = options.delete(:present) + descriptions[name] = options.delete(:desc) + formats[name] = options.delete(:format) initialize_setter(name, type, options) initialize_getter(name) diff --git a/lib/shallow_attributes/type.rb b/lib/shallow_attributes/type.rb index ef66fc1..b99b380 100644 --- a/lib/shallow_attributes/type.rb +++ b/lib/shallow_attributes/type.rb @@ -7,6 +7,13 @@ require 'shallow_attributes/type/time' require 'shallow_attributes/type/date' +# Boolean class for working with bool values +# +# @private +# +# @since 0.9.4 +class Boolean; end + module ShallowAttributes # Namespace for standard type classes # @@ -30,7 +37,8 @@ class InvalidValueError < TypeError ::Integer => ShallowAttributes::Type::Integer.new, ::String => ShallowAttributes::Type::String.new, ::Time => ShallowAttributes::Type::Time.new, - ::Date => ShallowAttributes::Type::Date.new + ::Date => ShallowAttributes::Type::Date.new, + ::Boolean => ShallowAttributes::Type::Boolean.new }.freeze class << self @@ -56,7 +64,10 @@ class << self # # @since 0.1.0 def coerce(type, value, options = {}) - type_instance(type).coerce(value, options) + instance = type_instance(type, value) + return instance.coerce(instance.attributes, options) if instance.respond_to? :attributes + + instance.coerce(value, options) end private @@ -78,8 +89,14 @@ def coerce(type, value, options = {}) # @return [Class] # # @since 0.1.0 - def type_instance(klass) - DEFAULT_TYPE_OBJECTS[klass] || ShallowAttributes::Type.const_get(klass.name).new + def type_instance(klass, value = {}) + return DEFAULT_TYPE_OBJECTS[klass] if DEFAULT_TYPE_OBJECTS[klass] + + instantiable = ShallowAttributes::Type.const_get(klass.name) + + return instantiable.new(value) if instantiable < ShallowAttributes + + instantiable.new end end end diff --git a/test/custom_types_test.rb b/test/custom_types_test.rb index b0955bf..a3473bf 100644 --- a/test/custom_types_test.rb +++ b/test/custom_types_test.rb @@ -152,5 +152,28 @@ class Person end end end + describe 'when custom type receives parameters not considered as attributes' do + let(:person) do + Person.new( + name: 'John', + address: { + street: 'Street', + number: '12' + } + ) + end + + it 'ignores the non existence parameter' do + hash = person.attributes + hash.must_equal({ + name: 'John', + addresses: [], + address: { + street: 'Street', + zipcode: '111111' + } + }) + end + end end end