diff options
Diffstat (limited to 'lib/hashie')
-rw-r--r-- | lib/hashie/extensions/deep_merge.rb | 17 | ||||
-rw-r--r-- | lib/hashie/utils.rb | 28 |
2 files changed, 44 insertions, 1 deletions
diff --git a/lib/hashie/extensions/deep_merge.rb b/lib/hashie/extensions/deep_merge.rb index 5363904..1890e8f 100644 --- a/lib/hashie/extensions/deep_merge.rb +++ b/lib/hashie/extensions/deep_merge.rb @@ -3,7 +3,7 @@ module Hashie module DeepMerge # Returns a new hash with +self+ and +other_hash+ merged recursively. def deep_merge(other_hash, &block) - copy = dup + copy = _deep_dup(self) copy.extend(Hashie::Extensions::DeepMerge) unless copy.respond_to?(:deep_merge!) copy.deep_merge!(other_hash, &block) end @@ -18,6 +18,21 @@ module Hashie private + def _deep_dup(hash) + copy = hash.dup + + copy.each do |key, value| + copy[key] = + if value.is_a?(::Hash) + _deep_dup(value) + else + Hashie::Utils.safe_dup(value) + end + end + + copy + end + def _recursive_merge(hash, other_hash, &block) other_hash.each do |k, v| hash[k] = diff --git a/lib/hashie/utils.rb b/lib/hashie/utils.rb index d8e05fe..5b55b9a 100644 --- a/lib/hashie/utils.rb +++ b/lib/hashie/utils.rb @@ -12,5 +12,33 @@ module Hashie "defined in #{bound_method.owner}" end end + + # Duplicates a value or returns the value when it is not duplicable + # + # @api public + # + # @param value [Object] the value to safely duplicate + # @return [Object] the duplicated value + def self.safe_dup(value) + case value + when Complex, FalseClass, NilClass, Rational, Method, Symbol, TrueClass, *integer_classes + value + else + value.dup + end + end + + # Lists the classes Ruby uses for integers + # + # @api private + # @return [Array<Class>] + def self.integer_classes + @integer_classes ||= + if const_defined?(:Fixnum) + [Fixnum, Bignum] # rubocop:disable Lint/UnifiedInteger + else + [Integer] + end + end end end |