init_copy 0.1.2 → 0.2.0
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/.rdoc_options +28 -0
- data/Gemfile +10 -1
- data/LICENSE.txt +1 -1
- data/README.md +162 -0
- data/Rakefile +8 -20
- data/init_copy.gemspec +26 -20
- data/lib/init_copy.rb +43 -86
- data/test/init_copy_test.rb +242 -0
- metadata +29 -71
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1620d2aa498e981be870fd3e0d671595b0407e557b54e40cf7e32b38b95158a8
|
4
|
+
data.tar.gz: 1b08062be47d208e59ed5a70e548f726d55936ccc000a84bbda5b2ed47119360
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 17b1bc267564f9f49c5b699581f522690bc13a63addbab7708bbb6af227970f3701c0f259d00d0d42b4c898e5b349324672b416395d5d0d34be151cf48994db0
|
7
|
+
data.tar.gz: e2973b90f3bd28a061904a1db08435b2f2a5af11c2a7bc4d14ce1a40bfbc7837099b0c8c786ea39b064714b041d87994420890ff6f6ae30afb621dac6f31d89b
|
data/.rdoc_options
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
---
|
2
|
+
charset: UTF-8
|
3
|
+
encoding: UTF-8
|
4
|
+
|
5
|
+
op_dir: doc
|
6
|
+
title: InitCopy
|
7
|
+
main_page: README.md
|
8
|
+
|
9
|
+
apply_default_exclude: true
|
10
|
+
embed_mixins: true
|
11
|
+
force_update: true
|
12
|
+
hyperlink_all: true
|
13
|
+
line_numbers: true
|
14
|
+
show_hash: true
|
15
|
+
skip_tests: true
|
16
|
+
|
17
|
+
exclude:
|
18
|
+
- /.git/
|
19
|
+
- /.github/
|
20
|
+
- /.idea/
|
21
|
+
- /doc/
|
22
|
+
- /pkg/
|
23
|
+
- /spec/
|
24
|
+
- /stock/
|
25
|
+
- /test/
|
26
|
+
- Gemfile
|
27
|
+
- Gemfile.lock
|
28
|
+
- Rakefile
|
data/Gemfile
CHANGED
@@ -1,7 +1,16 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
|
5
4
|
source 'https://rubygems.org'
|
6
5
|
|
7
6
|
gemspec
|
7
|
+
|
8
|
+
group :development,:test do
|
9
|
+
gem 'bundler' ,'~> 2.6'
|
10
|
+
gem 'rake' ,'~> 13.3'
|
11
|
+
gem 'rdoc' ,'~> 6.14'
|
12
|
+
end
|
13
|
+
|
14
|
+
group :test do
|
15
|
+
gem 'minitest' ,'~> 5.25'
|
16
|
+
end
|
data/LICENSE.txt
CHANGED
data/README.md
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
# InitCopy
|
2
|
+
|
3
|
+
[](https://badge.fury.io/rb/init_copy)
|
4
|
+
[](https://github.com/esotericpig/init_copy/actions/workflows/ci.yml)
|
5
|
+
|
6
|
+
[](https://github.com/esotericpig/init_copy)
|
7
|
+
[](CHANGELOG.md)
|
8
|
+
[](LICENSE.txt)
|
9
|
+
|
10
|
+
🧬 Easily use the correct `clone` or `dup` method in `initialize_copy`.
|
11
|
+
|
12
|
+
If we only use either `clone` or `dup` or we use `Marshal`, then that does not produce the correct behavior according to the [standard documentation](https://docs.ruby-lang.org/en/master/Object.html#method-i-dup-label-on+dup+vs+clone). This is because `clone` should preserve the internal state (e.g., the frozen state and extended modules), while `dup` should not. For example:
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
module SecretExt
|
16
|
+
def secret
|
17
|
+
'password'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
bob = 'Bob'
|
22
|
+
bob.extend(SecretExt)
|
23
|
+
bob.freeze
|
24
|
+
|
25
|
+
clone = bob.clone
|
26
|
+
dup = bob.dup
|
27
|
+
|
28
|
+
puts clone.frozen? #=> true
|
29
|
+
puts dup.frozen? #=> false
|
30
|
+
|
31
|
+
puts clone.secret #=> password
|
32
|
+
puts dup.secret #=> NoMethodError
|
33
|
+
```
|
34
|
+
|
35
|
+
To solve this issue in the past, we had to define both `initialize_clone` & `initialize_dup` and maintain two copies of all our deep-copy code. That sucks. 😞
|
36
|
+
|
37
|
+
🚀 Instead, *InitCopy* was created:
|
38
|
+
1. Install the gem `init_copy` ([RubyGems.org page](https://rubygems.org/gems/init_copy)).
|
39
|
+
2. Include `InitCopy` in your class/module.
|
40
|
+
3. Override the `init_copy(original)` method.
|
41
|
+
4. Use `ic_copy(var)`, instead of clone/dup.
|
42
|
+
|
43
|
+
Example usage:
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
require 'init_copy'
|
47
|
+
|
48
|
+
class JangoFett
|
49
|
+
include InitCopy
|
50
|
+
|
51
|
+
attr_reader :gear,:order66
|
52
|
+
|
53
|
+
def initialize
|
54
|
+
super
|
55
|
+
|
56
|
+
@gear = ['blaster','jetpack']
|
57
|
+
|
58
|
+
@order66 = Class.new do
|
59
|
+
undef_method :clone
|
60
|
+
undef_method :dup
|
61
|
+
end.new
|
62
|
+
end
|
63
|
+
|
64
|
+
protected
|
65
|
+
|
66
|
+
def init_copy(_orig)
|
67
|
+
super
|
68
|
+
|
69
|
+
@gear = ic_copy(@gear)
|
70
|
+
@order66 = ic_copy?(@order66) # Safe copy if no dup/clone.
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
jango = JangoFett.new
|
75
|
+
jango.freeze
|
76
|
+
|
77
|
+
boba1 = jango.clone
|
78
|
+
boba2 = jango.dup
|
79
|
+
|
80
|
+
jango.gear << 'vibroblade'
|
81
|
+
boba1.gear << 'implant'
|
82
|
+
|
83
|
+
puts jango.gear.inspect #=> ["blaster", "jetpack", "vibroblade"]
|
84
|
+
|
85
|
+
puts boba1.gear.inspect #=> ["blaster", "jetpack", "implant"]
|
86
|
+
puts boba2.gear.inspect #=> ["blaster", "jetpack"]
|
87
|
+
|
88
|
+
puts boba1.frozen? #=> true (clone)
|
89
|
+
puts boba2.frozen? #=> false (dup)
|
90
|
+
```
|
91
|
+
|
92
|
+
## // Contents
|
93
|
+
|
94
|
+
- [Setup](#-setup)
|
95
|
+
- [Hacking](#-hacking)
|
96
|
+
- [License](#-license)
|
97
|
+
|
98
|
+
## [//](#-contents) Setup
|
99
|
+
|
100
|
+
Pick your poison...
|
101
|
+
|
102
|
+
With the *RubyGems* CLI package manager:
|
103
|
+
|
104
|
+
```bash
|
105
|
+
gem install init_copy
|
106
|
+
```
|
107
|
+
|
108
|
+
In your *Gemspec*:
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
spec.add_dependency 'init_copy', '~> X.X'
|
112
|
+
```
|
113
|
+
|
114
|
+
In your *Gemfile*:
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
# Pick one...
|
118
|
+
gem 'init_copy', '~> X.X'
|
119
|
+
|
120
|
+
gem 'init_copy', git: 'https://github.com/esotericpig/init_copy.git', branch: 'main'
|
121
|
+
```
|
122
|
+
|
123
|
+
From source:
|
124
|
+
|
125
|
+
```bash
|
126
|
+
git clone 'https://github.com/esotericpig/init_copy.git'
|
127
|
+
cd init_copy
|
128
|
+
bundle install
|
129
|
+
bundle exec rake install:local
|
130
|
+
```
|
131
|
+
|
132
|
+
## [//](#-contents) Hacking
|
133
|
+
|
134
|
+
```bash
|
135
|
+
git clone 'https://github.com/esotericpig/init_copy.git'
|
136
|
+
cd init_copy
|
137
|
+
bundle install
|
138
|
+
bundle exec rake -T
|
139
|
+
```
|
140
|
+
|
141
|
+
Testing:
|
142
|
+
|
143
|
+
```bash
|
144
|
+
bundle exec rake test
|
145
|
+
```
|
146
|
+
|
147
|
+
Generating doc:
|
148
|
+
|
149
|
+
```bash
|
150
|
+
bundle exec rake clobber_doc doc
|
151
|
+
```
|
152
|
+
|
153
|
+
Installing:
|
154
|
+
|
155
|
+
```bash
|
156
|
+
bundle exec rake install:local
|
157
|
+
```
|
158
|
+
|
159
|
+
## [//](#-contents) License
|
160
|
+
|
161
|
+
Copyright (c) 2020-2025 Bradley Whited
|
162
|
+
[MIT License](LICENSE.txt)
|
data/Rakefile
CHANGED
@@ -1,39 +1,27 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
|
5
4
|
require 'bundler/gem_tasks'
|
6
5
|
|
7
6
|
require 'init_copy'
|
8
7
|
require 'rake/clean'
|
9
8
|
require 'rake/testtask'
|
10
|
-
require '
|
11
|
-
|
9
|
+
require 'rdoc/task'
|
12
10
|
|
13
|
-
CLEAN.exclude('.git/','stock/')
|
11
|
+
CLEAN.exclude('.git/','.github/','.idea/','stock/')
|
14
12
|
CLOBBER.include('doc/')
|
15
13
|
|
16
|
-
|
17
|
-
task default: [:test]
|
18
|
-
|
19
|
-
desc 'Generate doc (YARDoc)'
|
20
|
-
task :doc,%i[] => %i[yard]
|
14
|
+
task default: %i[test]
|
21
15
|
|
22
16
|
Rake::TestTask.new do |task|
|
23
17
|
task.libs = ['lib','test']
|
24
|
-
task.pattern =
|
25
|
-
task.
|
18
|
+
task.pattern = 'test/**/*_test.rb'
|
19
|
+
task.options = '--pride'
|
26
20
|
task.verbose = false
|
27
21
|
task.warning = true
|
28
22
|
end
|
29
23
|
|
30
|
-
|
31
|
-
task.
|
32
|
-
|
33
|
-
task.options += ['--files','CHANGELOG.md,LICENSE.txt']
|
34
|
-
task.options += ['--readme','README.md']
|
35
|
-
|
36
|
-
task.options << '--protected' # Show protected methods
|
37
|
-
#task.options += ['--template-path',File.join('yard','templates')]
|
38
|
-
task.options += ['--title',"InitCopy v#{InitCopy::VERSION} Doc"]
|
24
|
+
RDoc::Task.new(:doc) do |task|
|
25
|
+
task.rdoc_dir = 'doc'
|
26
|
+
task.title = "InitCopy v#{InitCopy::VERSION}"
|
39
27
|
end
|
data/init_copy.gemspec
CHANGED
@@ -1,39 +1,45 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
|
5
4
|
require_relative 'lib/init_copy'
|
6
5
|
|
7
|
-
|
8
6
|
Gem::Specification.new do |spec|
|
9
7
|
spec.name = 'init_copy'
|
10
8
|
spec.version = InitCopy::VERSION
|
11
|
-
spec.authors = ['
|
9
|
+
spec.authors = ['Bradley Whited']
|
12
10
|
spec.email = ['code@esotericpig.com']
|
13
11
|
spec.licenses = ['MIT']
|
14
12
|
spec.homepage = 'https://github.com/esotericpig/init_copy'
|
15
|
-
spec.summary = 'Easily use the
|
13
|
+
spec.summary = 'Easily use the correct clone or dup method in initialize_copy.'
|
16
14
|
spec.description = spec.summary
|
17
15
|
|
18
16
|
spec.metadata = {
|
19
|
-
'
|
20
|
-
'
|
21
|
-
'
|
22
|
-
'
|
17
|
+
'rubygems_mfa_required' => 'true',
|
18
|
+
'homepage_uri' => 'https://github.com/esotericpig/init_copy',
|
19
|
+
'source_code_uri' => 'https://github.com/esotericpig/init_copy',
|
20
|
+
'bug_tracker_uri' => 'https://github.com/esotericpig/init_copy/issues',
|
21
|
+
'changelog_uri' => 'https://github.com/esotericpig/init_copy/blob/main/CHANGELOG.md',
|
23
22
|
}
|
24
23
|
|
25
|
-
spec.require_paths = ['lib']
|
26
|
-
|
27
|
-
spec.files = Dir.glob(File.join("{#{spec.require_paths.join(',')}}",'**','*.{rb}')) +
|
28
|
-
%W[ Gemfile #{spec.name}.gemspec Rakefile ] +
|
29
|
-
%w[ LICENSE.txt ]
|
30
|
-
|
31
24
|
# Lowest version that isn't eol (end-of-life).
|
32
25
|
# - https://www.ruby-lang.org/en/downloads/branches/
|
33
|
-
spec.required_ruby_version = '>= 2
|
34
|
-
|
35
|
-
spec.
|
36
|
-
spec.
|
37
|
-
|
38
|
-
spec.
|
26
|
+
spec.required_ruby_version = '>= 3.2'
|
27
|
+
spec.require_paths = ['lib']
|
28
|
+
spec.bindir = 'bin'
|
29
|
+
spec.executables = []
|
30
|
+
|
31
|
+
spec.extra_rdoc_files = %w[LICENSE.txt README.md]
|
32
|
+
spec.rdoc_options = [
|
33
|
+
%w[--embed-mixins --hyperlink-all --line-numbers --show-hash],
|
34
|
+
'--main','README.md',
|
35
|
+
'--title',"InitCopy v#{InitCopy::VERSION}",
|
36
|
+
].flatten
|
37
|
+
|
38
|
+
spec.files = [
|
39
|
+
Dir.glob("{#{spec.require_paths.join(',')}}/**/*.{erb,rb}"),
|
40
|
+
Dir.glob("#{spec.bindir}/*"),
|
41
|
+
Dir.glob('{spec,test}/**/*.{erb,rb}'),
|
42
|
+
%W[Gemfile #{spec.name}.gemspec Rakefile .rdoc_options],
|
43
|
+
spec.extra_rdoc_files,
|
44
|
+
].flatten
|
39
45
|
end
|
data/lib/init_copy.rb
CHANGED
@@ -3,120 +3,77 @@
|
|
3
3
|
|
4
4
|
#--
|
5
5
|
# This file is part of InitCopy.
|
6
|
-
# Copyright (c) 2020
|
6
|
+
# Copyright (c) 2020 Bradley Whited
|
7
7
|
#
|
8
8
|
# SPDX-License-Identifier: MIT
|
9
9
|
#++
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
#
|
14
|
-
#
|
15
|
-
|
11
|
+
# Example usage:
|
12
|
+
# require 'init_copy'
|
13
|
+
#
|
14
|
+
# class JangoFett
|
15
|
+
# include InitCopy
|
16
|
+
#
|
17
|
+
# protected
|
18
|
+
#
|
19
|
+
# def init_copy(_orig)
|
20
|
+
# super
|
21
|
+
#
|
22
|
+
# @gear = ic_copy(@gear)
|
23
|
+
# @order66 = ic_copy?(@order66) # Safe copy if no dup/clone.
|
24
|
+
# end
|
25
|
+
# end
|
16
26
|
module InitCopy
|
17
|
-
VERSION = '0.
|
27
|
+
VERSION = '0.2.0'
|
18
28
|
|
19
|
-
|
29
|
+
def self.included(mod)
|
30
|
+
super
|
20
31
|
|
21
|
-
|
22
|
-
|
32
|
+
# NOTE: Can't use prepend(), else children's init_copy() won't call their parents', even with super().
|
33
|
+
mod.include(Copyable)
|
23
34
|
end
|
24
35
|
|
25
|
-
def self.
|
26
|
-
|
27
|
-
|
28
|
-
caller.each do |name|
|
29
|
-
if name.end_with?("clone'")
|
30
|
-
copy_name = :clone
|
31
|
-
break
|
32
|
-
end
|
33
|
-
|
34
|
-
if name.end_with?("dup'")
|
35
|
-
copy_name = :dup
|
36
|
-
break
|
37
|
-
end
|
38
|
-
end
|
36
|
+
def self.extended(mod)
|
37
|
+
super
|
39
38
|
|
40
|
-
|
39
|
+
mod.include(Copyable)
|
41
40
|
end
|
42
41
|
|
43
|
-
|
44
|
-
|
45
|
-
# @since 0.1.0
|
46
|
-
###
|
47
|
-
class Copier
|
48
|
-
attr_accessor :default_name
|
49
|
-
attr_accessor :name
|
50
|
-
|
51
|
-
def initialize(default_name=DEFAULT_COPY_NAME)
|
52
|
-
super()
|
53
|
-
|
54
|
-
@default_name = default_name
|
55
|
-
|
56
|
-
update_name
|
57
|
-
end
|
58
|
-
|
59
|
-
def copy(var)
|
60
|
-
return var.__send__(@name)
|
61
|
-
end
|
42
|
+
def self.prepended(mod)
|
43
|
+
super
|
62
44
|
|
63
|
-
|
64
|
-
|
65
|
-
end
|
66
|
-
|
67
|
-
def update_name
|
68
|
-
@name = InitCopy.find_copy_name(@default_name)
|
69
|
-
end
|
45
|
+
# User specifically requested to prepend.
|
46
|
+
mod.prepend(Copyable)
|
70
47
|
end
|
71
48
|
|
72
|
-
Copyer = Copier # Alias
|
73
|
-
|
74
|
-
###
|
75
|
-
# The instance variable name is long and obnoxious to reduce conflicts.
|
76
|
-
#
|
77
|
-
# @author Jonathan Bradley Whited
|
78
|
-
# @since 0.1.0
|
79
|
-
###
|
80
49
|
module Copyable
|
81
|
-
|
82
|
-
def initialize(*)
|
50
|
+
def initialize_clone(orig)
|
83
51
|
super
|
84
|
-
@init_copy_method_name = DEFAULT_COPY_NAME
|
85
|
-
end
|
86
52
|
|
87
|
-
|
88
|
-
@
|
89
|
-
|
53
|
+
# The instance variable name is long & obnoxious to reduce conflicts.
|
54
|
+
@__init_copy_method_name = :clone
|
55
|
+
init_copy(orig)
|
90
56
|
end
|
91
57
|
|
92
|
-
def initialize_dup(
|
93
|
-
@init_copy_method_name = :dup
|
58
|
+
def initialize_dup(orig)
|
94
59
|
super
|
95
|
-
end
|
96
60
|
|
97
|
-
|
98
|
-
|
99
|
-
super
|
100
|
-
end
|
101
|
-
|
102
|
-
def dup(*)
|
103
|
-
@init_copy_method_name = :dup
|
104
|
-
super
|
61
|
+
@__init_copy_method_name = :dup
|
62
|
+
init_copy(orig)
|
105
63
|
end
|
106
64
|
|
107
|
-
|
65
|
+
protected
|
108
66
|
|
109
|
-
def
|
110
|
-
return var.__send__(@init_copy_method_name)
|
67
|
+
def init_copy(_orig)
|
111
68
|
end
|
112
69
|
|
113
|
-
def
|
114
|
-
|
70
|
+
def ic_copy(var)
|
71
|
+
return var.__send__(@__init_copy_method_name)
|
72
|
+
end
|
115
73
|
|
116
|
-
|
117
|
-
|
74
|
+
def ic_copy?(var)
|
75
|
+
return var.__send__(@__init_copy_method_name) if var.respond_to?(@__init_copy_method_name)
|
76
|
+
return var
|
118
77
|
end
|
119
78
|
end
|
120
|
-
|
121
|
-
Copiable = Copyable # Alias
|
122
79
|
end
|
@@ -0,0 +1,242 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#--
|
5
|
+
# This file is part of InitCopy.
|
6
|
+
# Copyright (c) 2020 Bradley Whited
|
7
|
+
#
|
8
|
+
# SPDX-License-Identifier: MIT
|
9
|
+
#++
|
10
|
+
|
11
|
+
require 'minitest/autorun'
|
12
|
+
|
13
|
+
require 'init_copy'
|
14
|
+
|
15
|
+
class InitCopyTest < Minitest::Test
|
16
|
+
# def setup
|
17
|
+
# end
|
18
|
+
|
19
|
+
def test_include
|
20
|
+
%i[include extend prepend].each do |method|
|
21
|
+
sut_class = Class.new
|
22
|
+
sut_class.__send__(method,InitCopy)
|
23
|
+
|
24
|
+
assert_includes(sut_class.included_modules,InitCopy::Copyable,
|
25
|
+
"`#{method}` of InitCopy should include InitCopy::Copyable")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_no_copy
|
30
|
+
sut = TestBag.new
|
31
|
+
|
32
|
+
refute_deep_copy(sut,sut.clone,:clone)
|
33
|
+
refute_deep_copy(sut,sut.dup,:dup)
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_clone
|
37
|
+
sut = TestBagWithCopy.new
|
38
|
+
|
39
|
+
assert_deep_copy(sut,sut.clone,:clone)
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_dup
|
43
|
+
sut = TestBagWithCopy.new
|
44
|
+
|
45
|
+
assert_deep_copy(sut,sut.dup,:dup)
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_correct_clone_and_dup_behavior
|
49
|
+
sut_ext = Module.new do
|
50
|
+
def bonus
|
51
|
+
return 100
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
sut = TestBagWithCopy.new
|
56
|
+
sut.extend(sut_ext)
|
57
|
+
|
58
|
+
assert_deep_copy(sut,sut.clone,:clone)
|
59
|
+
assert_deep_copy(sut,sut.dup,:dup)
|
60
|
+
|
61
|
+
sut.nums.freeze
|
62
|
+
sut_clone = sut.clone
|
63
|
+
sut_dup = sut.dup
|
64
|
+
|
65
|
+
assert_predicate(sut.nums,:frozen?,'SUT nums should be frozen')
|
66
|
+
assert_respond_to(sut,:bonus,'SUT should have the bonus extension')
|
67
|
+
assert_equal(100,sut.bonus)
|
68
|
+
|
69
|
+
assert_predicate(sut_clone.nums,:frozen?,'clone should keep the nums as frozen')
|
70
|
+
assert_respond_to(sut_clone,:bonus,'clone should keep the bonus extension')
|
71
|
+
assert_equal(100,sut_clone.bonus)
|
72
|
+
|
73
|
+
refute_predicate(sut_dup.nums,:frozen?,'dup should remove the internal frozen state of nums')
|
74
|
+
refute_respond_to(sut_dup,:bonus,'dup should remove the bonus extension')
|
75
|
+
assert_raises(NoMethodError) { sut_dup.bonus }
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_safe_copy
|
79
|
+
sut = TestBagWithSafeCopy.new
|
80
|
+
|
81
|
+
assert_respond_to(sut.nums,:clone)
|
82
|
+
assert_respond_to(sut.nums,:dup)
|
83
|
+
|
84
|
+
assert_deep_copy(sut,sut.clone,:clone)
|
85
|
+
assert_deep_copy(sut,sut.dup,:dup)
|
86
|
+
|
87
|
+
class << sut.nums
|
88
|
+
undef_method :clone
|
89
|
+
undef_method :dup
|
90
|
+
end
|
91
|
+
|
92
|
+
refute_respond_to(sut.nums,:clone)
|
93
|
+
refute_respond_to(sut.nums,:dup)
|
94
|
+
|
95
|
+
refute_deep_copy(sut,sut.clone,:clone,is_safe_copy: true)
|
96
|
+
refute_deep_copy(sut,sut.dup,:dup,is_safe_copy: true)
|
97
|
+
|
98
|
+
# Make sure we didn't remove clone()/dup() for all arrays.
|
99
|
+
assert_respond_to([1,2,3],:clone)
|
100
|
+
assert_respond_to([1,2,3],:dup)
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_child_copy
|
104
|
+
sut_class = Class.new(TestBagWithCopy) do
|
105
|
+
attr_reader :strs
|
106
|
+
|
107
|
+
def initialize
|
108
|
+
super
|
109
|
+
|
110
|
+
@strs = %w[a b c]
|
111
|
+
end
|
112
|
+
|
113
|
+
def init_copy(*)
|
114
|
+
super
|
115
|
+
|
116
|
+
@strs = ic_copy(@strs)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
sut = sut_class.new
|
121
|
+
sut_clone = sut.clone
|
122
|
+
sut_dup = sut.dup
|
123
|
+
|
124
|
+
assert_deep_copy(sut,sut_clone,:clone)
|
125
|
+
assert_deep_copy(sut,sut_dup,:dup)
|
126
|
+
|
127
|
+
expected = %w[a b c]
|
128
|
+
|
129
|
+
refute_same(sut.strs,sut_clone.strs)
|
130
|
+
refute_same(sut.strs,sut_dup.strs)
|
131
|
+
assert_equal(expected,sut.strs)
|
132
|
+
assert_equal(expected,sut_clone.strs)
|
133
|
+
assert_equal(expected,sut_dup.strs)
|
134
|
+
|
135
|
+
sut.strs << 'd'
|
136
|
+
sut_clone.strs << 'e'
|
137
|
+
sut_dup.strs << 'f'
|
138
|
+
|
139
|
+
assert_equal(%w[a b c d],sut.strs)
|
140
|
+
assert_equal(%w[a b c e],sut_clone.strs)
|
141
|
+
assert_equal(%w[a b c f],sut_dup.strs)
|
142
|
+
end
|
143
|
+
|
144
|
+
def assert_deep_copy(sut,sut_copy,copy_method_name)
|
145
|
+
refute_same(sut,sut_copy)
|
146
|
+
|
147
|
+
assert_nil(sut.init_copy_method_name)
|
148
|
+
assert_equal(copy_method_name,sut_copy.init_copy_method_name)
|
149
|
+
|
150
|
+
assert_nil(sut.orig)
|
151
|
+
assert_same(sut,sut_copy.orig)
|
152
|
+
|
153
|
+
expected = [1,2,3]
|
154
|
+
|
155
|
+
refute_same(sut.nums,sut_copy.nums)
|
156
|
+
assert_equal(expected,sut.nums)
|
157
|
+
assert_equal(expected,sut_copy.nums)
|
158
|
+
|
159
|
+
sut.nums << 4
|
160
|
+
sut_copy.nums << 5
|
161
|
+
|
162
|
+
assert_equal([1,2,3,4],sut.nums)
|
163
|
+
assert_equal([1,2,3,5],sut_copy.nums)
|
164
|
+
|
165
|
+
# Reset.
|
166
|
+
sut.nums.pop
|
167
|
+
sut_copy.nums.pop
|
168
|
+
end
|
169
|
+
|
170
|
+
def refute_deep_copy(sut,sut_copy,copy_method_name,is_safe_copy: false)
|
171
|
+
refute_same(sut,sut_copy)
|
172
|
+
|
173
|
+
assert_nil(sut.init_copy_method_name)
|
174
|
+
assert_equal(copy_method_name,sut_copy.init_copy_method_name)
|
175
|
+
|
176
|
+
assert_nil(sut.orig)
|
177
|
+
|
178
|
+
if is_safe_copy
|
179
|
+
assert_same(sut,sut_copy.orig)
|
180
|
+
else
|
181
|
+
assert_nil(sut_copy.orig)
|
182
|
+
end
|
183
|
+
|
184
|
+
expected = [1,2,3]
|
185
|
+
|
186
|
+
assert_same(sut.nums,sut_copy.nums)
|
187
|
+
assert_equal(expected,sut.nums)
|
188
|
+
assert_equal(expected,sut_copy.nums)
|
189
|
+
|
190
|
+
sut.nums << 4
|
191
|
+
sut_copy.nums << 5
|
192
|
+
|
193
|
+
expected = [1,2,3,4,5]
|
194
|
+
|
195
|
+
assert_equal(expected,sut.nums)
|
196
|
+
assert_equal(expected,sut_copy.nums)
|
197
|
+
|
198
|
+
# Reset.
|
199
|
+
sut.nums.pop(2)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
class TestBag
|
204
|
+
include InitCopy
|
205
|
+
|
206
|
+
attr_reader :orig
|
207
|
+
attr_reader :nums
|
208
|
+
|
209
|
+
def initialize
|
210
|
+
super
|
211
|
+
|
212
|
+
@__init_copy_method_name = nil
|
213
|
+
@orig = nil
|
214
|
+
@nums = [1,2,3]
|
215
|
+
end
|
216
|
+
|
217
|
+
def init_copy_method_name
|
218
|
+
return @__init_copy_method_name
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
class TestBagWithCopy < TestBag
|
223
|
+
protected
|
224
|
+
|
225
|
+
def init_copy(orig)
|
226
|
+
super
|
227
|
+
|
228
|
+
@orig = orig
|
229
|
+
@nums = ic_copy(@nums)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
class TestBagWithSafeCopy < TestBag
|
234
|
+
protected
|
235
|
+
|
236
|
+
def init_copy(orig)
|
237
|
+
super
|
238
|
+
|
239
|
+
@orig = orig
|
240
|
+
@nums = ic_copy?(@nums)
|
241
|
+
end
|
242
|
+
end
|
metadata
CHANGED
@@ -1,108 +1,66 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: init_copy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
8
|
-
autorequire:
|
7
|
+
- Bradley Whited
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
12
|
-
dependencies:
|
13
|
-
|
14
|
-
name: bundler
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '2.2'
|
20
|
-
type: :development
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '2.2'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: minitest
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '5.14'
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '5.14'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: rake
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '13.0'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '13.0'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: yard
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - "~>"
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0.9'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - "~>"
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '0.9'
|
69
|
-
description: Easily use the appropriate clone/dup method in initialize_copy.
|
11
|
+
date: 2025-06-06 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Easily use the correct clone or dup method in initialize_copy.
|
70
14
|
email:
|
71
15
|
- code@esotericpig.com
|
72
16
|
executables: []
|
73
17
|
extensions: []
|
74
|
-
extra_rdoc_files:
|
18
|
+
extra_rdoc_files:
|
19
|
+
- LICENSE.txt
|
20
|
+
- README.md
|
75
21
|
files:
|
22
|
+
- ".rdoc_options"
|
76
23
|
- Gemfile
|
77
24
|
- LICENSE.txt
|
25
|
+
- README.md
|
78
26
|
- Rakefile
|
79
27
|
- init_copy.gemspec
|
80
28
|
- lib/init_copy.rb
|
29
|
+
- test/init_copy_test.rb
|
81
30
|
homepage: https://github.com/esotericpig/init_copy
|
82
31
|
licenses:
|
83
32
|
- MIT
|
84
33
|
metadata:
|
85
|
-
|
86
|
-
changelog_uri: https://github.com/esotericpig/init_copy/blob/master/CHANGELOG.md
|
34
|
+
rubygems_mfa_required: 'true'
|
87
35
|
homepage_uri: https://github.com/esotericpig/init_copy
|
88
36
|
source_code_uri: https://github.com/esotericpig/init_copy
|
89
|
-
|
90
|
-
|
37
|
+
bug_tracker_uri: https://github.com/esotericpig/init_copy/issues
|
38
|
+
changelog_uri: https://github.com/esotericpig/init_copy/blob/main/CHANGELOG.md
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options:
|
41
|
+
- "--embed-mixins"
|
42
|
+
- "--hyperlink-all"
|
43
|
+
- "--line-numbers"
|
44
|
+
- "--show-hash"
|
45
|
+
- "--main"
|
46
|
+
- README.md
|
47
|
+
- "--title"
|
48
|
+
- InitCopy v0.2.0
|
91
49
|
require_paths:
|
92
50
|
- lib
|
93
51
|
required_ruby_version: !ruby/object:Gem::Requirement
|
94
52
|
requirements:
|
95
53
|
- - ">="
|
96
54
|
- !ruby/object:Gem::Version
|
97
|
-
version: '2
|
55
|
+
version: '3.2'
|
98
56
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
57
|
requirements:
|
100
58
|
- - ">="
|
101
59
|
- !ruby/object:Gem::Version
|
102
60
|
version: '0'
|
103
61
|
requirements: []
|
104
|
-
rubygems_version: 3.
|
105
|
-
signing_key:
|
62
|
+
rubygems_version: 3.5.21
|
63
|
+
signing_key:
|
106
64
|
specification_version: 4
|
107
|
-
summary: Easily use the
|
65
|
+
summary: Easily use the correct clone or dup method in initialize_copy.
|
108
66
|
test_files: []
|