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 +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