full_dup 0.0.5 → 0.0.6
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 +58 -14
- data/lib/full_dup/array.rb +10 -4
- data/lib/full_dup/hash.rb +10 -4
- data/lib/full_dup/object.rb +10 -4
- data/lib/full_dup/struct.rb +10 -4
- data/lib/full_dup/use_dup.rb +19 -0
- data/lib/full_dup/use_self.rb +36 -0
- data/lib/full_dup/version.rb +1 -1
- data/lib/full_dup.rb +4 -29
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 20cf85cb4234f06a7460867e7ea8106d39354c23
|
4
|
+
data.tar.gz: d6a798fe6cd7b325372d97b70b1502229f30fb09
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1dfd98c630f82771af60cc0edc6db998258e1e6dcdbc39062a8129194244c34e725df68bfaa12b63a5feb1d8d10fd5e16c0b707902e1ed7a1de716d697ccb344
|
7
|
+
data.tar.gz: e47dcb7ba1044b94894e45c2241722dfee313b5b51ae93e32a1865945b6fa3d1221425e14a39704dd4402d383d392683095337df49557fca9225aac55611955e
|
data/README.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
# FullDup
|
2
2
|
|
3
|
+
The full_dup gem adds the full_dup method to all objects descended from the
|
4
|
+
Object class. While this gem makes extensive use of monkey patching, it does
|
5
|
+
not modify the behaviour of any existing methods. This is done to minimize
|
6
|
+
the risk of breaking any existing code.
|
7
|
+
|
8
|
+
New for version 0.0.6, now 84% faster (at least in my tests).
|
9
|
+
|
3
10
|
The standard dup method creates a fresh instance of most (non-scalar) objects
|
4
11
|
but does not process internal state. This internal state remains aliased in the
|
5
12
|
duplicated copy. The full_dup method digs deep and makes copies of these
|
@@ -13,13 +20,24 @@ it does mean that the dup operation must be applied with great care.
|
|
13
20
|
|
14
21
|
Unlike the standard dup method, the full\_dup method does not throw an
|
15
22
|
exception when it sees un-duppable value objects like 42 or true. These values
|
16
|
-
simply return themselves. This is correct because those types of objects
|
17
|
-
not
|
23
|
+
simply return themselves. This is deemed correct because those types of objects
|
24
|
+
are immutable and do not need to be duped. Instead of raising an exception,
|
25
|
+
the code returns the immutable object instead.
|
18
26
|
|
19
27
|
Another issue that this gem deals with is that of data with looping reference
|
20
28
|
chains. To handle this, the code tracks object ID values and does not re-dup
|
21
29
|
data that has already been duped. Thus even nasty edge cases are handled
|
22
|
-
without any special effort on the part of the application programmer.
|
30
|
+
without any special effort on the part of the application programmer. Note though
|
31
|
+
that this also means that it is important that the object id be correctly
|
32
|
+
implemented. Fortunately, this is done by default in Ruby.
|
33
|
+
|
34
|
+
If you wish to implement your own object id for your own special classes:
|
35
|
+
1. Don't! If object_id is broken,
|
36
|
+
then full_dup (and a whole lot of other things too) will also be broken!
|
37
|
+
2. It's all on you to do as good a job as Ruby. Like the Ruby object id method,
|
38
|
+
your method must create id values that are unique to each object and are perfectly
|
39
|
+
repeatable for that object.
|
40
|
+
3. Really DON'T! I have never found a valid reason for doing so. I doubt that one exists.
|
23
41
|
|
24
42
|
## Family Overview
|
25
43
|
|
@@ -93,20 +111,46 @@ array:
|
|
93
111
|
```ruby
|
94
112
|
my_array.define_singleton_method(:full_dup_exclude) { [0, 1] }
|
95
113
|
```
|
96
|
-
<br>**Possible Red Flag** There is a catch here. The dup
|
97
|
-
duplicate singleton methods (unlike the clone
|
98
|
-
made in this manner will lose the attached full_dup_exclude
|
99
|
-
important to retain singleton methods, consider using the
|
100
|
-
instead.
|
114
|
+
<br>**Possible Red Flag** There is a catch here. The dup and full_dup methods
|
115
|
+
do not duplicate singleton methods (unlike the clone and full_clone methods).
|
116
|
+
Thus any duplicates made in this manner will lose the attached full_dup_exclude
|
117
|
+
method. If it is important to retain singleton methods, consider using the
|
118
|
+
full_clone gem instead.
|
101
119
|
|
102
|
-
|
120
|
+
### irbt
|
103
121
|
|
104
|
-
The full_dup gem
|
105
|
-
|
106
|
-
|
107
|
-
If object_id is broken, then full_dup and hashes and ... will also be
|
108
|
-
broken!
|
122
|
+
The root folder of the full_dup gem contains the file irbt.rb. This program
|
123
|
+
opens up the irb repl with the full_dup gem preloaded and is useful for trying
|
124
|
+
out the gem interactively.
|
109
125
|
|
126
|
+
By default, irbt will load the system gem version of full dup. The following
|
127
|
+
interactive session demonstrates the difference between dup and full_dup
|
128
|
+
|
129
|
+
```
|
130
|
+
C:\Sites\full_dup>ruby irbt.rb
|
131
|
+
Starting an IRB console with full_dup loaded.
|
132
|
+
full_dup loaded from gem: 0.0.5
|
133
|
+
irb(main):001:0> a = ["a", "b", "c"]
|
134
|
+
=> ["a", "b", "c"]
|
135
|
+
irb(main):002:0> b = a.dup
|
136
|
+
=> ["a", "b", "c"]
|
137
|
+
irb(main):003:0> c = a.full_dup
|
138
|
+
=> ["a", "b", "c"]
|
139
|
+
irb(main):004:0> a[0] << "foo"
|
140
|
+
=> "afoo"
|
141
|
+
irb(main):005:0> a
|
142
|
+
=> ["afoo", "b", "c"]
|
143
|
+
irb(main):006:0> b
|
144
|
+
=> ["afoo", "b", "c"]
|
145
|
+
irb(main):007:0> c
|
146
|
+
=> ["a", "b", "c"]
|
147
|
+
irb(main):008:0>
|
148
|
+
```
|
149
|
+
To load the local copy of full_dup use:
|
150
|
+
```
|
151
|
+
>ruby irbt.rb local #optional irb args go here.
|
152
|
+
#etc etc etc...
|
153
|
+
```
|
110
154
|
|
111
155
|
## Contributing
|
112
156
|
|
data/lib/full_dup/array.rb
CHANGED
@@ -7,14 +7,20 @@ class Array
|
|
7
7
|
progress[object_id] = result = dup
|
8
8
|
exclude = full_dup_exclude
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
unless exclude.include?(name)
|
10
|
+
if exclude.empty?
|
11
|
+
each_index do |name|
|
13
12
|
value = result[name]
|
14
13
|
value = progress[value.object_id] || value.full_dup(progress)
|
15
14
|
result[name] = value
|
16
15
|
end
|
17
|
-
|
16
|
+
else
|
17
|
+
each_index do |name|
|
18
|
+
unless exclude.include?(name)
|
19
|
+
value = result[name]
|
20
|
+
value = progress[value.object_id] || value.full_dup(progress)
|
21
|
+
result[name] = value
|
22
|
+
end
|
23
|
+
end
|
18
24
|
end
|
19
25
|
|
20
26
|
result
|
data/lib/full_dup/hash.rb
CHANGED
@@ -7,14 +7,20 @@ class Hash
|
|
7
7
|
progress[object_id] = result = dup
|
8
8
|
exclude = full_dup_exclude
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
unless exclude.include?(name)
|
10
|
+
if exclude.empty?
|
11
|
+
each_key do |name|
|
13
12
|
value = result[name]
|
14
13
|
value = progress[value.object_id] || value.full_dup(progress)
|
15
14
|
result[name] = value
|
16
15
|
end
|
17
|
-
|
16
|
+
else
|
17
|
+
each_key do |name|
|
18
|
+
unless exclude.include?(name)
|
19
|
+
value = result[name]
|
20
|
+
value = progress[value.object_id] || value.full_dup(progress)
|
21
|
+
result[name] = value
|
22
|
+
end
|
23
|
+
end
|
18
24
|
end
|
19
25
|
|
20
26
|
result
|
data/lib/full_dup/object.rb
CHANGED
@@ -12,14 +12,20 @@ class Object
|
|
12
12
|
progress[object_id] = result = dup
|
13
13
|
exclude = full_dup_exclude
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
unless exclude.include?(name)
|
15
|
+
if exclude.empty?
|
16
|
+
instance_variables.each do |name|
|
18
17
|
value = result.instance_variable_get(name)
|
19
18
|
value = progress[value.object_id] || value.full_dup(progress)
|
20
19
|
result.instance_variable_set(name, value)
|
21
20
|
end
|
22
|
-
|
21
|
+
else
|
22
|
+
instance_variables.each do |name|
|
23
|
+
unless exclude.include?(name)
|
24
|
+
value = result.instance_variable_get(name)
|
25
|
+
value = progress[value.object_id] || value.full_dup(progress)
|
26
|
+
result.instance_variable_set(name, value)
|
27
|
+
end
|
28
|
+
end
|
23
29
|
end
|
24
30
|
|
25
31
|
result
|
data/lib/full_dup/struct.rb
CHANGED
@@ -7,14 +7,20 @@ class Struct
|
|
7
7
|
progress[object_id] = result = dup
|
8
8
|
exclude = full_dup_exclude
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
unless exclude.include?(name)
|
10
|
+
if exclude.empty?
|
11
|
+
members.each do |name|
|
13
12
|
value = result[name]
|
14
13
|
value = progress[value.object_id] || value.full_dup(progress)
|
15
14
|
result[name] = value
|
16
15
|
end
|
17
|
-
|
16
|
+
else
|
17
|
+
members.each do |name|
|
18
|
+
unless exclude.include?(name)
|
19
|
+
value = result[name]
|
20
|
+
value = progress[value.object_id] || value.full_dup(progress)
|
21
|
+
result[name] = value
|
22
|
+
end
|
23
|
+
end
|
18
24
|
end
|
19
25
|
|
20
26
|
result
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module FullDupSelf
|
4
|
+
def full_dup(_progress=nil)
|
5
|
+
self
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class Numeric
|
10
|
+
include FullDupSelf
|
11
|
+
end
|
12
|
+
|
13
|
+
class NilClass
|
14
|
+
include FullDupSelf
|
15
|
+
end
|
16
|
+
|
17
|
+
class TrueClass
|
18
|
+
include FullDupSelf
|
19
|
+
end
|
20
|
+
|
21
|
+
class FalseClass
|
22
|
+
include FullDupSelf
|
23
|
+
end
|
24
|
+
|
25
|
+
class Symbol
|
26
|
+
include FullDupSelf
|
27
|
+
end
|
28
|
+
|
29
|
+
class Regexp
|
30
|
+
include FullDupSelf
|
31
|
+
end
|
32
|
+
|
33
|
+
class Thread
|
34
|
+
include FullDupSelf
|
35
|
+
end
|
36
|
+
|
data/lib/full_dup/version.rb
CHANGED
data/lib/full_dup.rb
CHANGED
@@ -1,37 +1,12 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
|
+
# A deep, safe, recursive variant of the dup method. The full_dup method.
|
4
|
+
|
5
|
+
require_relative 'full_dup/use_self'
|
6
|
+
require_relative 'full_dup/use_dup'
|
3
7
|
require_relative 'full_dup/version'
|
4
8
|
require_relative 'full_dup/object'
|
5
9
|
require_relative 'full_dup/array'
|
6
10
|
require_relative 'full_dup/hash'
|
7
11
|
require_relative 'full_dup/struct'
|
8
12
|
|
9
|
-
module FullDup
|
10
|
-
def full_dup(_progress={})
|
11
|
-
self
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
class Numeric
|
16
|
-
include FullDup
|
17
|
-
end
|
18
|
-
|
19
|
-
class NilClass
|
20
|
-
include FullDup
|
21
|
-
end
|
22
|
-
|
23
|
-
class TrueClass
|
24
|
-
include FullDup
|
25
|
-
end
|
26
|
-
|
27
|
-
class FalseClass
|
28
|
-
include FullDup
|
29
|
-
end
|
30
|
-
|
31
|
-
class Symbol
|
32
|
-
include FullDup
|
33
|
-
end
|
34
|
-
|
35
|
-
class Regexp
|
36
|
-
include FullDup
|
37
|
-
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: full_dup
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Camilleri
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-08-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -85,6 +85,8 @@ files:
|
|
85
85
|
- lib/full_dup/hash.rb
|
86
86
|
- lib/full_dup/object.rb
|
87
87
|
- lib/full_dup/struct.rb
|
88
|
+
- lib/full_dup/use_dup.rb
|
89
|
+
- lib/full_dup/use_self.rb
|
88
90
|
- lib/full_dup/version.rb
|
89
91
|
- rakefile.rb
|
90
92
|
homepage: https://github.com/PeterCamilleri/full_dup
|
@@ -107,9 +109,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
107
109
|
version: '0'
|
108
110
|
requirements: []
|
109
111
|
rubyforge_project:
|
110
|
-
rubygems_version: 2.2
|
112
|
+
rubygems_version: 2.5.2
|
111
113
|
signing_key:
|
112
114
|
specification_version: 4
|
113
115
|
summary: A dup variant that performs a deep copy.
|
114
116
|
test_files: []
|
115
|
-
has_rdoc:
|