deep_dup 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2d00f8bfe1ee27f10defaf6f00fd1da009bac911
4
- data.tar.gz: 8f6c8f10cd798bf95e47df1bd5798caaee00d696
3
+ metadata.gz: ceac246a3817ea4e391592dbd51e7e56548d7eca
4
+ data.tar.gz: 41519b1a8812200f74a25706452c1155d9b1a8f5
5
5
  SHA512:
6
- metadata.gz: 2f090c0109e6ab2fe5b7c2d5570de9aeed3cb0470b72e0584d3e9b000fc23c733a325efe3ce4f14dd82e448869bdbfc518d10db3c7eb9e2c1248a5a13410efc7
7
- data.tar.gz: 9e73b27787434ee36d1504f0d8f1c49b317f6fd1ff87c8d1d53fce14f38b19f35403e59f90d16aad11a6e25ba8b035db70b2ecb6ed77839118932e7c3aa5408f
6
+ metadata.gz: 4b10b7fd154bf2490d69cb5944d1acf6f6865cf3c8fc4b9e4ed2c2ffd79ccab35c29e0d425fe55d11315450bc3088068f56294f0ea0b602b99256a986e40f0e7
7
+ data.tar.gz: a3bdef85413b1d39034d7e7c46e5b7e7c8086a7a112bbebc14cbc734aad9f691fdd65b513faff93bc1d7129ebd33aed6c97aa8479c9da523153caa9cf8130bfb
data/README.md CHANGED
@@ -13,6 +13,10 @@ dupped = DeepDup.deep_dup('chunky')
13
13
  dupped = DeepDup.deep_dup(['chunky', [:bacon, { hi: 5 }]])
14
14
  dupped = DeepDup.deep_dup(['a', :a, 1, { bacon: { chunky: 'yeah' } }])
15
15
  dupped = DeepDup.deep_dup(SomeClass.new)
16
+
17
+ array = [1, 2]
18
+ array << array
19
+ dupped = DeepDup.deep_dup(array)
16
20
  ```
17
21
 
18
22
  With monkey patching
@@ -24,6 +28,10 @@ dupped = 'chunky'.deep_dup
24
28
  dupped = ['chunky', [:bacon, { hi: 5 }]].deep_dup
25
29
  dupped = ['a', :a, 1, { bacon: { chunky: 'yeah' } }].deep_dup
26
30
  dupped = SomeClass.new.deep_dup
31
+
32
+ array = [1, 2]
33
+ array << array
34
+ dupped = array.deep_dup
27
35
  ```
28
36
  ## Installation
29
37
 
@@ -54,3 +62,7 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/ollie/
54
62
  ## License
55
63
 
56
64
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
65
+
66
+ ## Credits
67
+
68
+ Thanks [Ice Nine](https://github.com/dkubb/ice_nine) and [Rails](https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/object/duplicable.rb) for inspiration.
@@ -10,6 +10,10 @@ require 'deep_dup/version'
10
10
  # dupped = DeepDup.deep_dup(['a', :a, 1, { bacon: { chunky: 'yeah' } }])
11
11
  # dupped = DeepDup.deep_dup(SomeClass.new)
12
12
  #
13
+ # array = [1, 2]
14
+ # array << array
15
+ # dupped = DeepDup.deep_dup(array)
16
+ #
13
17
  # @example With monkey patching
14
18
  # require 'deep_dup/core_ext/object'
15
19
  #
@@ -17,6 +21,10 @@ require 'deep_dup/version'
17
21
  # dupped = ['chunky', [:bacon, { hi: 5 }]].deep_dup
18
22
  # dupped = ['a', :a, 1, { bacon: { chunky: 'yeah' } }].deep_dup
19
23
  # dupped = SomeClass.new.deep_dup
24
+ #
25
+ # array = [1, 2]
26
+ # array << array
27
+ # dupped = array.deep_dup
20
28
  module DeepDup
21
29
  # Deep duplicate any object.
22
30
  #
@@ -26,23 +34,67 @@ module DeepDup
26
34
  # dupped = DeepDup.deep_dup(['a', :a, 1, { bacon: { chunky: 'yeah' } }])
27
35
  # dupped = DeepDup.deep_dup(SomeClass.new)
28
36
  #
37
+ # array = [1, 2]
38
+ # array << array
39
+ # dupped = DeepDup.deep_dup(array)
40
+ #
29
41
  # @param object [Object] Pretty much anything.
42
+ # @param cache [Hash] Cache +object_id+s to prevent stack overflow on
43
+ # recursive data structures.
30
44
  #
31
45
  # @return [Object] Dupped object if possible.
32
- def self.deep_dup(object) # rubocop:disable Metrics/MethodLength
46
+ def self.deep_dup(object, cache = {}) # rubocop:disable Metrics/MethodLength
33
47
  case object
34
48
  when String
35
49
  object.dup
36
50
  when nil, false, true, Numeric, Symbol, Method
37
51
  object
38
52
  when Array
39
- object.map { |item| deep_dup(item) }
53
+ cache_object(object, [], cache) do |new_object|
54
+ object.each do |item|
55
+ new_object << deep_dup(item, cache)
56
+ end
57
+ end
40
58
  when Hash
41
- object.each.with_object({}) do |(key, value), hash|
42
- hash[deep_dup(key)] = deep_dup(value)
59
+ cache_object(object, {}, cache) do |new_object|
60
+ object.each do |key, value|
61
+ new_object[deep_dup(key, cache)] = deep_dup(value, cache)
62
+ end
43
63
  end
44
64
  else # Object, Class
45
65
  object.dup
46
66
  end
47
67
  end
68
+
69
+ # Prevent infinite recursion on recursive data structures.
70
+ #
71
+ # Imagine an array that has only one item which is a reference to itself.
72
+ # When entering this method, the cache is empty so we create a new array
73
+ # and map the original object's id to this newly created object.
74
+ #
75
+ # We then give control back to +deep_dup+ so that it can go on and do the
76
+ # adding, which will call itself with the same array and enter this method
77
+ # again.
78
+ #
79
+ # But this time, since the object is the same, we know the duplicate object
80
+ # because we stored in in our little cache. So just go ahead and return it
81
+ # otherwise it would result in an infinite recursion.
82
+ #
83
+ # @param object [Array, Hash] Original object reference.
84
+ # @param new_object [Array, Hash] The dupped object reference.
85
+ # @param cache [Hash] Map from original object_id to dupped object.
86
+ #
87
+ # @yieldparam new_object [Array, Hash] The dupped object reference.
88
+ #
89
+ # @return [Array, Hash] The dupped object.
90
+ def self.cache_object(object, new_object, cache)
91
+ object_id = object.object_id
92
+ dupped_object = cache[object_id] # Did we already visit this object?
93
+
94
+ return dupped_object if dupped_object # Yes, return it, prevent overflow.
95
+
96
+ cache[object_id] = new_object # Map the original object id to the new object.
97
+ yield(new_object) # Let +deep_dup+ do the job.
98
+ new_object # Just return it to +deep_dup+.
99
+ end
48
100
  end
@@ -13,6 +13,10 @@ module DeepDup
13
13
  # dupped = ['a', :a, 1, { bacon: { chunky: 'yeah' } }].deep_dup
14
14
  # dupped = SomeClass.new.deep_dup
15
15
  #
16
+ # array = [1, 2]
17
+ # array << array
18
+ # dupped = array.deep_dup
19
+ #
16
20
  # @return [Object] Dupped object if possible.
17
21
  def deep_dup
18
22
  DeepDup.deep_dup(self)
@@ -1,4 +1,4 @@
1
1
  module DeepDup
2
2
  # Version number, happy now?
3
- VERSION = '0.0.1'
3
+ VERSION = '0.0.2'
4
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: deep_dup
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oldrich Vetesnik