lib/lazy_mapper.rb in lazy_mapper-0.3.1 vs lib/lazy_mapper.rb in lazy_mapper-0.3.2

- old
+ new

@@ -1,5 +1,7 @@ +# frozen_string_literal: true + require 'bigdecimal' require 'bigdecimal/util' require 'time' # @@ -51,11 +53,11 @@ DEFAULT_VALUES = { String => '', Integer => 0, Numeric => 0, Float => 0.0, - BigDecimal => BigDecimal.new('0'), + BigDecimal => BigDecimal(0), Array => [] }.freeze # # Adds a mapper for a give type @@ -152,19 +154,20 @@ # User => User.method(:new) }) # def self.from unmapped_data, mappers: {} return nil if unmapped_data.nil? fail TypeError, "#{ unmapped_data.inspect } is not a Hash" unless unmapped_data.respond_to? :to_h + instance = new instance.send :unmapped_data=, unmapped_data.to_h instance.send :mappers=, mappers instance end def self.from_json *args, &block # :nodoc: warn "#{ self }.from_json is deprecated. Use #{ self }.from instead." - from *args, &block + from(*args, &block) end # # Defines an attribute and creates a reader and a writer for it. # The writer verifies the type of it's supplied value. @@ -302,31 +305,32 @@ def add_mapper_for(type, &block) mappers[type] = block end def to_h - attributes.each_with_object({}) {|(key, _value), h| + attributes.each_with_object({}) { |(key, _value), h| h[key] = self.send key } end def inspect @__under_inspection__ ||= 0 - return "<#{ self.class.name } ... >" if @__under_inspection__ > 0 + return "<#{ self.class.name } ... >" if @__under_inspection__.positive? + @__under_inspection__ += 1 present_attributes = attributes.keys.each_with_object({}) { |name, memo| - value = self.send name - memo[name] = value unless value.nil? + ivar = IVAR[name] + next unless self.instance_variable_defined? ivar + + memo[name] = self.instance_variable_get ivar } - "<#{ self.class.name } #{ present_attributes.map { |k, v| k.to_s + ': ' + v.inspect }.join(', ') } >" + res = "<#{ self.class.name } #{ present_attributes.map { |k, v| k.to_s + ': ' + v.inspect }.join(', ') } >" @__under_inspection__ -= 1 res end - protected - # # Defines how to map an attribute name # to the corresponding name in the unmapped # JSON object. # @@ -356,30 +360,37 @@ def attributes self.class.attributes end def mapped_value(name, unmapped_value, type, map: mapping_for(name, type), default: default_value(type)) - if unmapped_value.nil? - # Duplicate to prevent accidental sharing between instances - default.dup - else - fail ArgumentError, "missing mapper for #{ name } (#{ type }). Unmapped value: #{ unmapped_value.inspect }" if map.nil? - result = map.arity > 1 ? map.call(unmapped_value, self) : map.call(unmapped_value) - result + return default.dup if unmapped_value.nil? # Duplicate to prevent accidental sharing between instances + + if map.nil? + fail ArgumentError, "missing mapper for #{ name } (#{ type }). "\ + "Unmapped value: #{ unmapped_value.inspect }" end + + return map.call(unmapped_value, self) if map.arity > 1 + + map.call(unmapped_value) end def check_type! value, type, allow_nil: permitted_types = allow_nil ? Array(type) + [ NilClass ] : Array(type) - fail TypeError.new "#{ self.class.name }: #{ value.inspect } is a #{ value.class } but was supposed to be a #{ humanize_list permitted_types, conjunction: ' or ' }" unless permitted_types.any? value.method(:is_a?) + return if permitted_types.any? value.method(:is_a?) + + fail TypeError.new "#{ self.class.name }: "\ + "#{ value.inspect } is a #{ value.class } "\ + "but was supposed to be a #{ humanize_list permitted_types, conjunction: ' or ' }" end # [1,2,3] -> "1, 2 and 3" # [1, 2] -> "1 and 2" # [1] -> "1" def humanize_list list, separator: ', ', conjunction: ' and ' *all_but_last, last = list return last if all_but_last.empty? + [ all_but_last.join(separator), last ].join conjunction end def memoize name, ivar = IVAR[name] send WRITER[name], yield unless instance_variable_defined?(ivar)