summaryrefslogtreecommitdiff
path: root/lib/hashie
diff options
context:
space:
mode:
Diffstat (limited to 'lib/hashie')
-rw-r--r--lib/hashie/extensions/deep_merge.rb17
-rw-r--r--lib/hashie/utils.rb28
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