deep_dup 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +12 -0
- data/lib/deep_dup.rb +56 -4
- data/lib/deep_dup/core_ext/object.rb +4 -0
- data/lib/deep_dup/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ceac246a3817ea4e391592dbd51e7e56548d7eca
|
4
|
+
data.tar.gz: 41519b1a8812200f74a25706452c1155d9b1a8f5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
data/lib/deep_dup.rb
CHANGED
@@ -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
|
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
|
42
|
-
|
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)
|
data/lib/deep_dup/version.rb
CHANGED