diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/hashie/extensions/coercion.rb | 32 | ||||
-rw-r--r-- | lib/hashie/extensions/dash/indifferent_access.rb | 21 | ||||
-rw-r--r-- | lib/hashie/extensions/dash/property_translation.rb | 4 | ||||
-rw-r--r-- | lib/hashie/extensions/deep_locate.rb | 8 | ||||
-rw-r--r-- | lib/hashie/extensions/indifferent_access.rb | 4 | ||||
-rw-r--r-- | lib/hashie/extensions/mash/safe_assignment.rb | 4 | ||||
-rw-r--r-- | lib/hashie/extensions/strict_key_access.rb | 9 | ||||
-rw-r--r-- | lib/hashie/hash.rb | 25 | ||||
-rw-r--r-- | lib/hashie/mash.rb | 13 |
9 files changed, 84 insertions, 36 deletions
diff --git a/lib/hashie/extensions/coercion.rb b/lib/hashie/extensions/coercion.rb index e3f5011..88be97a 100644 --- a/lib/hashie/extensions/coercion.rb +++ b/lib/hashie/extensions/coercion.rb @@ -1,5 +1,9 @@ module Hashie - class CoercionError < StandardError; end + class CoercionError < StandardError + def initialize(key, value, into, message) + super("Cannot coerce property #{key.inspect} from #{value.class} to #{into}: #{message}") + end + end module Extensions module Coercion @@ -12,20 +16,22 @@ module Hashie Symbol => :to_sym }.freeze - ABSTRACT_CORE_TYPES = if RubyVersion.new(RUBY_VERSION) >= RubyVersion.new('2.4.0') - { Numeric => [Integer, Float, Complex, Rational] } - else - { - Integer => [Fixnum, Bignum], # rubocop:disable Lint/UnifiedInteger - Numeric => [Fixnum, Bignum, Float, Complex, Rational] # rubocop:disable Lint/UnifiedInteger - } - end + ABSTRACT_CORE_TYPES = + if RubyVersion.new(RUBY_VERSION) >= RubyVersion.new('2.4.0') + { Numeric => [Integer, Float, Complex, Rational] } + else + { + Integer => [Fixnum, Bignum], # rubocop:disable Lint/UnifiedInteger + Numeric => [Fixnum, Bignum, Float, Complex, Rational] # rubocop:disable Lint/UnifiedInteger + } + end def self.included(base) base.send :include, InstanceMethods - base.extend ClassMethods # NOTE: we wanna make sure we first define set_value_with_coercion before extending - - base.send :alias_method, :set_value_without_coercion, :[]= unless base.method_defined?(:set_value_without_coercion) + base.extend ClassMethods + unless base.method_defined?(:set_value_without_coercion) + base.send :alias_method, :set_value_without_coercion, :[]= + end base.send :alias_method, :[]=, :set_value_with_coercion end @@ -37,7 +43,7 @@ module Hashie begin value = self.class.fetch_coercion(into).call(value) rescue NoMethodError, TypeError => e - raise CoercionError, "Cannot coerce property #{key.inspect} from #{value.class} to #{into}: #{e.message}" + raise CoercionError.new(key, value, into, e.message) end end diff --git a/lib/hashie/extensions/dash/indifferent_access.rb b/lib/hashie/extensions/dash/indifferent_access.rb index 9d1b87b..204cae6 100644 --- a/lib/hashie/extensions/dash/indifferent_access.rb +++ b/lib/hashie/extensions/dash/indifferent_access.rb @@ -7,11 +7,23 @@ module Hashie base.send :include, Hashie::Extensions::IndifferentAccess end + def self.maybe_extend(base) + return unless requires_class_methods?(base) + + base.extend(ClassMethods) + end + + def self.requires_class_methods?(klass) + klass <= Hashie::Dash && + !klass.singleton_class.included_modules.include?(ClassMethods) + end + private_class_method :requires_class_methods? + module ClassMethods # Check to see if the specified property has already been # defined. def property?(name) - name = translations[name.to_sym] if included_modules.include?(Hashie::Extensions::Dash::PropertyTranslation) && translation_exists?(name) + name = translations[name.to_sym] if translation_for?(name) name = name.to_s !!properties.find { |property| property.to_s == name } end @@ -30,6 +42,13 @@ module Hashie name = name.to_s !!transforms.keys.find { |key| key.to_s == name } end + + private + + def translation_for?(name) + included_modules.include?(Hashie::Extensions::Dash::PropertyTranslation) && + translation_exists?(name) + end end end end diff --git a/lib/hashie/extensions/dash/property_translation.rb b/lib/hashie/extensions/dash/property_translation.rb index 85bfb89..f5bf081 100644 --- a/lib/hashie/extensions/dash/property_translation.rb +++ b/lib/hashie/extensions/dash/property_translation.rb @@ -58,7 +58,9 @@ module Hashie end def permitted_input_keys - @permitted_input_keys ||= properties.map { |property| inverse_translations.fetch property, property } + @permitted_input_keys ||= + properties + .map { |property| inverse_translations.fetch property, property } end # Defines a property on the Trash. Options are as follows: diff --git a/lib/hashie/extensions/deep_locate.rb b/lib/hashie/extensions/deep_locate.rb index 3577e93..62e1be2 100644 --- a/lib/hashie/extensions/deep_locate.rb +++ b/lib/hashie/extensions/deep_locate.rb @@ -62,7 +62,7 @@ module Hashie end def self._construct_key_comparator(search_key, object) - search_key = search_key.to_s if defined?(::ActiveSupport::HashWithIndifferentAccess) && object.is_a?(::ActiveSupport::HashWithIndifferentAccess) + search_key = search_key.to_s if activesupport_indifferent?(object) search_key = search_key.to_s if object.respond_to?(:indifferent_access?) && object.indifferent_access? lambda do |non_callable_object| @@ -93,6 +93,12 @@ module Hashie comparator.call(key, value, object) end private_class_method :_match_comparator? + + def self.activesupport_indifferent?(object) + defined?(::ActiveSupport::HashWithIndifferentAccess) && + object.is_a?(::ActiveSupport::HashWithIndifferentAccess) + end + private_class_method :activesupport_indifferent? end end end diff --git a/lib/hashie/extensions/indifferent_access.rb b/lib/hashie/extensions/indifferent_access.rb index 4f5bd2c..e3d2d63 100644 --- a/lib/hashie/extensions/indifferent_access.rb +++ b/lib/hashie/extensions/indifferent_access.rb @@ -24,9 +24,7 @@ module Hashie # module IndifferentAccess def self.included(base) - Hashie::Extensions::Dash::IndifferentAccess::ClassMethods.tap do |extension| - base.extend(extension) if base <= Hashie::Dash && !base.singleton_class.included_modules.include?(extension) - end + Hashie::Extensions::Dash::IndifferentAccess.maybe_extend(base) base.class_eval do alias_method :regular_writer, :[]= unless method_defined?(:regular_writer) diff --git a/lib/hashie/extensions/mash/safe_assignment.rb b/lib/hashie/extensions/mash/safe_assignment.rb index b1b2046..dcf7488 100644 --- a/lib/hashie/extensions/mash/safe_assignment.rb +++ b/lib/hashie/extensions/mash/safe_assignment.rb @@ -3,7 +3,9 @@ module Hashie module Mash module SafeAssignment def custom_writer(key, *args) #:nodoc: - raise ArgumentError, "The property #{key} clashes with an existing method." if !key?(key) && respond_to?(key, true) + if !key?(key) && respond_to?(key, true) + raise ArgumentError, "The property #{key} clashes with an existing method." + end super end diff --git a/lib/hashie/extensions/strict_key_access.rb b/lib/hashie/extensions/strict_key_access.rb index 0822c53..0edd698 100644 --- a/lib/hashie/extensions/strict_key_access.rb +++ b/lib/hashie/extensions/strict_key_access.rb @@ -15,12 +15,15 @@ module Hashie # >> hash[:cow] # KeyError: key not found: :cow # - # NOTE: For googlers coming from Python to Ruby, this extension makes a Hash behave more like a "Dictionary". + # NOTE: For googlers coming from Python to Ruby, this extension makes a Hash + # behave more like a "Dictionary". # module StrictKeyAccess class DefaultError < StandardError - def initialize(msg = 'Setting or using a default with Hashie::Extensions::StrictKeyAccess does not make sense', *args) - super + def initialize + super( + 'Setting or using a default with Hashie::Extensions::StrictKeyAccess does not make sense' + ) end end diff --git a/lib/hashie/hash.rb b/lib/hashie/hash.rb index 0eade03..7a97ef6 100644 --- a/lib/hashie/hash.rb +++ b/lib/hashie/hash.rb @@ -18,20 +18,21 @@ module Hashie def to_hash(options = {}) out = {} each_key do |k| - assignment_key = if options[:stringify_keys] - k.to_s - elsif options[:symbolize_keys] - k.to_s.to_sym - else - k - end + assignment_key = + if options[:stringify_keys] + k.to_s + elsif options[:symbolize_keys] + k.to_s.to_sym + else + k + end if self[k].is_a?(Array) out[assignment_key] ||= [] self[k].each do |array_object| - out[assignment_key] << (array_object.is_a?(Hash) ? flexibly_convert_to_hash(array_object, options) : array_object) + out[assignment_key] << maybe_convert_to_hash(array_object, options) end else - out[assignment_key] = self[k].is_a?(Hash) || self[k].respond_to?(:to_hash) ? flexibly_convert_to_hash(self[k], options) : self[k] + out[assignment_key] = maybe_convert_to_hash(self[k], options) end end out @@ -44,6 +45,12 @@ module Hashie private + def maybe_convert_to_hash(object, options) + return object unless object.is_a?(Hash) || object.respond_to?(:to_hash) + + flexibly_convert_to_hash(object, options) + end + def flexibly_convert_to_hash(object, options = {}) if object.method(:to_hash).arity.zero? object.to_hash diff --git a/lib/hashie/mash.rb b/lib/hashie/mash.rb index bc5873c..02ccc3f 100644 --- a/lib/hashie/mash.rb +++ b/lib/hashie/mash.rb @@ -16,8 +16,10 @@ module Hashie # * No punctuation: Returns the value of the hash for that key, or nil if none exists. # * Assignment (<tt>=</tt>): Sets the attribute of the given method name. # * Existence (<tt>?</tt>): Returns true or false depending on whether that key has been set. - # * Bang (<tt>!</tt>): Forces the existence of this key, used for deep Mashes. Think of it as "touch" for mashes. - # * Under Bang (<tt>_</tt>): Like Bang, but returns a new Mash rather than creating a key. Used to test existance in deep Mashes. + # * Bang (<tt>!</tt>): Forces the existence of this key, used for deep Mashes. Think of it + # as "touch" for mashes. + # * Under Bang (<tt>_</tt>): Like Bang, but returns a new Mash rather than creating a key. + # Used to test existance in deep Mashes. # # == Basic Example # @@ -64,8 +66,11 @@ module Hashie ALLOWED_SUFFIXES = %w[? ! = _].freeze class CannotDisableMashWarnings < StandardError - def initialize(message = 'You cannot disable warnings on the base Mash class. Please subclass the Mash and disable it in the subclass.') - super(message) + def initialize + super( + 'You cannot disable warnings on the base Mash class. ' \ + 'Please subclass the Mash and disable it in the subclass.' + ) end end |