init_copy 0.1.2 → 0.3.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 +29 -0
- data/Gemfile +10 -1
- data/LICENSE.txt +1 -1
- data/README.md +171 -0
- data/Rakefile +9 -21
- data/init_copy.gemspec +27 -22
- data/lib/init_copy/version.rb +13 -0
- data/lib/init_copy.rb +33 -96
- data/test/init_copy_test.rb +237 -0
- metadata +30 -71
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f2ea381fdf2b5c0bec710f2b219f87e2f897e8bba17246591982617e02a5024c
|
4
|
+
data.tar.gz: c33f202bb2301400918c86fc49a8acf0a43be8f82f5e7e2df1dc6ca9935fc4c4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 36b93091f59641bf0ea2fc2a7c520815f285e24aa5136d7e03c1e837811084f2b62e6040f82e98a1facd9e6b0930834558f7df7783cfe01a60a17b20d99152c9
|
7
|
+
data.tar.gz: fb2e3f6d74272af1061f73794814874bdb7d76f16c7998fdd9cfd41d1c5d17a7eda9985a0e0724be9fa16e1a55ba64f557ae431d93eff9a2637fc6bffab1312f
|
data/.rdoc_options
ADDED
@@ -0,0 +1,29 @@
|
|
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
|
+
markup: markdown
|
15
|
+
show_hash: true
|
16
|
+
skip_tests: true
|
17
|
+
|
18
|
+
exclude:
|
19
|
+
- /.git/
|
20
|
+
- /.github/
|
21
|
+
- /.idea/
|
22
|
+
- /doc/
|
23
|
+
- /pkg/
|
24
|
+
- /spec/
|
25
|
+
- /stock/
|
26
|
+
- /test/
|
27
|
+
- Gemfile
|
28
|
+
- Gemfile.lock
|
29
|
+
- 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,171 @@
|
|
1
|
+
# InitCopy
|
2
|
+
|
3
|
+
[](https://badge.fury.io/rb/init_copy)
|
4
|
+
[](https://github.com/esotericpig/init_copy/actions/workflows/ci.yml)
|
5
|
+
[](https://github.com/esotericpig/init_copy)
|
6
|
+
[](CHANGELOG.md)
|
7
|
+
[](LICENSE.txt)
|
8
|
+
|
9
|
+
🧬 Easily use the correct `clone` or `dup` method in `initialize_copy`.
|
10
|
+
|
11
|
+
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:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
module SecretExt
|
15
|
+
def secret
|
16
|
+
'password'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Init vars.
|
21
|
+
bob = 'Bob'
|
22
|
+
bob.extend(SecretExt)
|
23
|
+
bob.freeze
|
24
|
+
|
25
|
+
clone = bob.clone
|
26
|
+
dup = bob.dup
|
27
|
+
|
28
|
+
# Check vars.
|
29
|
+
puts clone.frozen? #=> true
|
30
|
+
puts dup.frozen? #=> false
|
31
|
+
|
32
|
+
puts clone.secret #=> password
|
33
|
+
puts dup.secret #=> NoMethodError
|
34
|
+
```
|
35
|
+
|
36
|
+
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. 😞
|
37
|
+
|
38
|
+
🚀 Instead, *InitCopy* was created:
|
39
|
+
|
40
|
+
1. Install the gem `init_copy` ([on RubyGems.org](https://rubygems.org/gems/init_copy)).
|
41
|
+
2. Include `InitCopy::Able` in your class/module.
|
42
|
+
3. Override the `init_copy(original)` method.
|
43
|
+
4. Use `ic_copy(var)`, instead of clone/dup.
|
44
|
+
|
45
|
+
Example usage:
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
require 'init_copy'
|
49
|
+
|
50
|
+
class JangoFett
|
51
|
+
include InitCopy::Able
|
52
|
+
|
53
|
+
attr_reader :gear,:bounties,:order66
|
54
|
+
|
55
|
+
def initialize
|
56
|
+
super
|
57
|
+
|
58
|
+
@gear = ['blaster','jetpack']
|
59
|
+
@bounties = ['Padmé','Vosa']
|
60
|
+
|
61
|
+
@order66 = Class.new do
|
62
|
+
undef_method :clone
|
63
|
+
undef_method :dup
|
64
|
+
end.new
|
65
|
+
end
|
66
|
+
|
67
|
+
protected
|
68
|
+
|
69
|
+
def init_copy(_orig)
|
70
|
+
super
|
71
|
+
|
72
|
+
@gear = ic_copy(@gear)
|
73
|
+
@bounties = ic_copy(@bounties)
|
74
|
+
|
75
|
+
@order66 = ic_copy?(@order66) # Safe copy if no dup/clone.
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# Init vars.
|
80
|
+
jango = JangoFett.new
|
81
|
+
jango.bounties.freeze
|
82
|
+
|
83
|
+
boba1 = jango.clone
|
84
|
+
boba2 = jango.dup
|
85
|
+
|
86
|
+
jango.gear << 'vibroblade'
|
87
|
+
boba1.gear << 'implant'
|
88
|
+
|
89
|
+
# Check vars.
|
90
|
+
puts jango.gear.inspect #=> ["blaster", "jetpack", "vibroblade"]
|
91
|
+
|
92
|
+
puts boba1.gear.inspect #=> ["blaster", "jetpack", "implant"]
|
93
|
+
puts boba2.gear.inspect #=> ["blaster", "jetpack"]
|
94
|
+
|
95
|
+
puts boba1.bounties.inspect #=> ["Padmé", "Vosa"]
|
96
|
+
puts boba2.bounties.inspect #=> ["Padmé", "Vosa"]
|
97
|
+
|
98
|
+
puts boba1.bounties.frozen? #=> true (clone)
|
99
|
+
puts boba2.bounties.frozen? #=> false (dup)
|
100
|
+
```
|
101
|
+
|
102
|
+
## // Contents
|
103
|
+
|
104
|
+
- [Setup](#-setup)
|
105
|
+
- [Hacking](#-hacking)
|
106
|
+
- [License](#-license)
|
107
|
+
|
108
|
+
## [//](#-contents) Setup
|
109
|
+
|
110
|
+
Pick your poison...
|
111
|
+
|
112
|
+
With the *RubyGems* CLI package manager:
|
113
|
+
|
114
|
+
```bash
|
115
|
+
gem install init_copy
|
116
|
+
```
|
117
|
+
|
118
|
+
In your *Gemspec*:
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
spec.add_dependency 'init_copy', '~> X.X'
|
122
|
+
```
|
123
|
+
|
124
|
+
In your *Gemfile*:
|
125
|
+
|
126
|
+
```ruby
|
127
|
+
# Pick your poison...
|
128
|
+
gem 'init_copy', '~> X.X'
|
129
|
+
gem 'init_copy', git: 'https://github.com/esotericpig/init_copy.git', branch: 'main'
|
130
|
+
```
|
131
|
+
|
132
|
+
From source:
|
133
|
+
|
134
|
+
```bash
|
135
|
+
git clone --depth 1 'https://github.com/esotericpig/init_copy.git'
|
136
|
+
cd init_copy
|
137
|
+
bundle install
|
138
|
+
bundle exec rake install:local
|
139
|
+
```
|
140
|
+
|
141
|
+
## [//](#-contents) Hacking
|
142
|
+
|
143
|
+
```bash
|
144
|
+
git clone 'https://github.com/esotericpig/init_copy.git'
|
145
|
+
cd init_copy
|
146
|
+
bundle install
|
147
|
+
bundle exec rake -T
|
148
|
+
```
|
149
|
+
|
150
|
+
Testing:
|
151
|
+
|
152
|
+
```bash
|
153
|
+
bundle exec rake test
|
154
|
+
```
|
155
|
+
|
156
|
+
Generating doc:
|
157
|
+
|
158
|
+
```bash
|
159
|
+
bundle exec rake clobber_doc doc
|
160
|
+
```
|
161
|
+
|
162
|
+
Installing:
|
163
|
+
|
164
|
+
```bash
|
165
|
+
bundle exec rake install:local
|
166
|
+
```
|
167
|
+
|
168
|
+
## [//](#-contents) License
|
169
|
+
|
170
|
+
Copyright (c) 2020-2025 Bradley Whited
|
171
|
+
[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
|
-
require 'init_copy'
|
6
|
+
require 'init_copy/version'
|
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,44 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
|
5
|
-
require_relative 'lib/init_copy'
|
6
|
-
|
4
|
+
require_relative 'lib/init_copy/version'
|
7
5
|
|
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
|
-
# Lowest version that isn't eol (end-of-life).
|
32
24
|
# - https://www.ruby-lang.org/en/downloads/branches/
|
33
|
-
spec.required_ruby_version = '>=
|
34
|
-
|
35
|
-
spec.
|
36
|
-
spec.
|
37
|
-
|
38
|
-
spec.
|
25
|
+
spec.required_ruby_version = '>= 3.1'
|
26
|
+
spec.require_paths = ['lib']
|
27
|
+
spec.bindir = 'bin'
|
28
|
+
spec.executables = []
|
29
|
+
|
30
|
+
spec.extra_rdoc_files = %w[LICENSE.txt README.md]
|
31
|
+
spec.rdoc_options = [
|
32
|
+
%w[--embed-mixins --hyperlink-all --line-numbers --show-hash],
|
33
|
+
'--main','README.md',
|
34
|
+
'--title',"InitCopy v#{InitCopy::VERSION}",
|
35
|
+
].flatten
|
36
|
+
|
37
|
+
spec.files = [
|
38
|
+
Dir.glob("{#{spec.require_paths.join(',')}}/**/*.{erb,rb}"),
|
39
|
+
Dir.glob("#{spec.bindir}/*"),
|
40
|
+
Dir.glob('{spec,test}/**/*.{erb,rb}'),
|
41
|
+
%W[Gemfile #{spec.name}.gemspec Rakefile .rdoc_options],
|
42
|
+
spec.extra_rdoc_files,
|
43
|
+
].flatten
|
39
44
|
end
|
data/lib/init_copy.rb
CHANGED
@@ -3,120 +3,57 @@
|
|
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
|
+
require 'init_copy/version'
|
11
12
|
|
12
|
-
|
13
|
-
#
|
14
|
-
#
|
15
|
-
|
13
|
+
# Example usage:
|
14
|
+
# require 'init_copy'
|
15
|
+
#
|
16
|
+
# class JangoFett
|
17
|
+
# include InitCopy::Able
|
18
|
+
#
|
19
|
+
# protected
|
20
|
+
#
|
21
|
+
# def init_copy(_orig)
|
22
|
+
# super
|
23
|
+
#
|
24
|
+
# @gear = ic_copy(@gear)
|
25
|
+
# @order66 = ic_copy?(@order66) # Safe copy if no dup/clone.
|
26
|
+
# end
|
27
|
+
# end
|
16
28
|
module InitCopy
|
17
|
-
|
18
|
-
|
19
|
-
DEFAULT_COPY_NAME = :dup
|
20
|
-
|
21
|
-
def self.new(default_name=DEFAULT_COPY_NAME)
|
22
|
-
return Copier.new(default_name)
|
23
|
-
end
|
24
|
-
|
25
|
-
def self.find_copy_name(default_name=DEFAULT_COPY_NAME)
|
26
|
-
copy_name = default_name
|
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
|
39
|
-
|
40
|
-
return copy_name
|
41
|
-
end
|
42
|
-
|
43
|
-
###
|
44
|
-
# @author Jonathan Bradley Whited
|
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
|
62
|
-
|
63
|
-
def safe_copy(var)
|
64
|
-
return var.respond_to?(@name) ? var.__send__(@name) : var
|
65
|
-
end
|
66
|
-
|
67
|
-
def update_name
|
68
|
-
@name = InitCopy.find_copy_name(@default_name)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
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
|
-
module Copyable
|
81
|
-
# @since 0.1.1
|
82
|
-
def initialize(*)
|
29
|
+
module Able
|
30
|
+
def initialize_clone(orig)
|
83
31
|
super
|
84
|
-
@init_copy_method_name = DEFAULT_COPY_NAME
|
85
|
-
end
|
86
32
|
|
87
|
-
|
88
|
-
@
|
89
|
-
|
33
|
+
# The instance var name is long & obnoxious to reduce conflicts.
|
34
|
+
@__init_copy_method_name = :clone
|
35
|
+
init_copy(orig)
|
90
36
|
end
|
91
37
|
|
92
|
-
def initialize_dup(
|
93
|
-
@init_copy_method_name = :dup
|
38
|
+
def initialize_dup(orig)
|
94
39
|
super
|
95
|
-
end
|
96
40
|
|
97
|
-
|
98
|
-
|
99
|
-
super
|
41
|
+
@__init_copy_method_name = :dup
|
42
|
+
init_copy(orig)
|
100
43
|
end
|
101
44
|
|
102
|
-
|
103
|
-
@init_copy_method_name = :dup
|
104
|
-
super
|
105
|
-
end
|
106
|
-
|
107
|
-
private
|
45
|
+
protected
|
108
46
|
|
109
|
-
def
|
110
|
-
return var.__send__(@init_copy_method_name)
|
47
|
+
def init_copy(_orig)
|
111
48
|
end
|
112
49
|
|
113
|
-
def
|
114
|
-
|
50
|
+
def ic_copy(var)
|
51
|
+
return var.__send__(@__init_copy_method_name)
|
52
|
+
end
|
115
53
|
|
116
|
-
|
117
|
-
|
54
|
+
def ic_copy?(var)
|
55
|
+
return var.__send__(@__init_copy_method_name) if var.respond_to?(@__init_copy_method_name)
|
56
|
+
return var
|
118
57
|
end
|
119
58
|
end
|
120
|
-
|
121
|
-
Copiable = Copyable # Alias
|
122
59
|
end
|
@@ -0,0 +1,237 @@
|
|
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
|
+
describe InitCopy do
|
16
|
+
it 'has a correct version' do
|
17
|
+
_(InitCopy::VERSION).must_match(/\d+\.\d+\.\d+(-[0-9A-Za-z\-.]+)?(\+[0-9A-Za-z\-.]+)?/)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.add_basic_copy_tests
|
21
|
+
it 'is not the same as the copies' do
|
22
|
+
_(@sut).wont_be_same_as(@sut_clone)
|
23
|
+
_(@sut).wont_be_same_as(@sut_dup)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'has the correct copy method name' do
|
27
|
+
_(@sut.init_copy_method_name).must_be_nil
|
28
|
+
_(@sut_clone.init_copy_method_name).must_equal(:clone)
|
29
|
+
_(@sut_dup.init_copy_method_name).must_equal(:dup)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.add_deep_copy_tests(is_frozen: false)
|
34
|
+
it 'has the correct original' do
|
35
|
+
_(@sut.orig).must_be_nil
|
36
|
+
_(@sut_clone.orig).must_be_same_as(@sut)
|
37
|
+
_(@sut_dup.orig).must_be_same_as(@sut)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'does a deep copy' do
|
41
|
+
_(@sut.nums).wont_be_same_as(@sut_clone.nums)
|
42
|
+
_(@sut.nums).wont_be_same_as(@sut_dup.nums)
|
43
|
+
|
44
|
+
expected = [1,2,3]
|
45
|
+
|
46
|
+
_(@sut.nums).must_equal(expected)
|
47
|
+
_(@sut_clone.nums).must_equal(expected)
|
48
|
+
_(@sut_dup.nums).must_equal(expected)
|
49
|
+
|
50
|
+
if !is_frozen
|
51
|
+
@sut.nums << 4
|
52
|
+
@sut_clone.nums << 5
|
53
|
+
@sut_dup.nums << 6
|
54
|
+
|
55
|
+
_(@sut.nums).must_equal([1,2,3,4])
|
56
|
+
_(@sut_clone.nums).must_equal([1,2,3,5])
|
57
|
+
_(@sut_dup.nums).must_equal([1,2,3,6])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe 'without copy' do
|
63
|
+
before do
|
64
|
+
@sut = TestBag.new
|
65
|
+
@sut_clone = @sut.clone
|
66
|
+
@sut_dup = @sut.dup
|
67
|
+
end
|
68
|
+
|
69
|
+
add_basic_copy_tests
|
70
|
+
|
71
|
+
it 'has no original' do
|
72
|
+
_(@sut.orig).must_be_nil
|
73
|
+
_(@sut_clone.orig).must_be_nil
|
74
|
+
_(@sut_dup.orig).must_be_nil
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'does not do a deep copy' do
|
78
|
+
_(@sut.nums).must_be_same_as(@sut_clone.nums)
|
79
|
+
_(@sut.nums).must_be_same_as(@sut_dup.nums)
|
80
|
+
|
81
|
+
expected = [1,2,3]
|
82
|
+
|
83
|
+
_(@sut.nums).must_equal(expected)
|
84
|
+
_(@sut_clone.nums).must_equal(expected)
|
85
|
+
_(@sut_dup.nums).must_equal(expected)
|
86
|
+
|
87
|
+
@sut.nums << 4
|
88
|
+
@sut_clone.nums << 5
|
89
|
+
@sut_dup.nums << 6
|
90
|
+
|
91
|
+
expected = [1,2,3,4,5,6]
|
92
|
+
|
93
|
+
_(@sut.nums).must_equal(expected)
|
94
|
+
_(@sut_clone.nums).must_equal(expected)
|
95
|
+
_(@sut_dup.nums).must_equal(expected)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe 'with copy' do
|
100
|
+
before do
|
101
|
+
@sut = TestBagWithCopy.new
|
102
|
+
@sut_clone = @sut.clone
|
103
|
+
@sut_dup = @sut.dup
|
104
|
+
end
|
105
|
+
|
106
|
+
add_basic_copy_tests
|
107
|
+
add_deep_copy_tests
|
108
|
+
end
|
109
|
+
|
110
|
+
describe 'with copy and internal state' do
|
111
|
+
before do
|
112
|
+
@sut = TestBagWithCopy.new
|
113
|
+
|
114
|
+
@sut.nums.extend(
|
115
|
+
Module.new do
|
116
|
+
def bonus
|
117
|
+
return 110
|
118
|
+
end
|
119
|
+
end
|
120
|
+
)
|
121
|
+
@sut.nums.freeze
|
122
|
+
|
123
|
+
@sut_clone = @sut.clone
|
124
|
+
@sut_dup = @sut.dup
|
125
|
+
end
|
126
|
+
|
127
|
+
add_basic_copy_tests
|
128
|
+
add_deep_copy_tests(is_frozen: true)
|
129
|
+
|
130
|
+
it 'has the correct bonus extension' do
|
131
|
+
_(@sut.nums).must_respond_to(:bonus,'SUT should have the nums bonus extension')
|
132
|
+
_(@sut.nums.bonus).must_equal(110)
|
133
|
+
|
134
|
+
_(@sut_clone.nums).must_respond_to(:bonus,'clone should keep the nums bonus extension')
|
135
|
+
_(@sut_clone.nums.bonus).must_equal(110)
|
136
|
+
|
137
|
+
_(@sut_dup.nums).wont_respond_to(:bonus,'dup should remove the nums bonus extension')
|
138
|
+
_ { @sut_dup.bonus }.must_raise(NoMethodError)
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'has the correct frozen state' do
|
142
|
+
_(@sut.nums.frozen?).must_equal(true,'SUT should have the nums as frozen')
|
143
|
+
_(@sut_clone.nums.frozen?).must_equal(true,'clone should keep the nums as frozen')
|
144
|
+
_(@sut_dup.nums.frozen?).must_equal(false,'dup should remove the nums as frozen')
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
describe 'child with copy and unsafe var' do
|
149
|
+
before do
|
150
|
+
@sut = TestBagChildWithCopyAndUnsafe.new
|
151
|
+
@sut_clone = @sut.clone
|
152
|
+
@sut_dup = @sut.dup
|
153
|
+
end
|
154
|
+
|
155
|
+
add_basic_copy_tests
|
156
|
+
add_deep_copy_tests
|
157
|
+
|
158
|
+
it 'does a deep copy of the strs' do
|
159
|
+
_(@sut.strs).wont_be_same_as(@sut_clone.strs)
|
160
|
+
_(@sut.strs).wont_be_same_as(@sut_dup.strs)
|
161
|
+
|
162
|
+
expected = %w[a b c]
|
163
|
+
|
164
|
+
_(@sut.strs).must_equal(expected)
|
165
|
+
_(@sut_clone.strs).must_equal(expected)
|
166
|
+
_(@sut_dup.strs).must_equal(expected)
|
167
|
+
|
168
|
+
@sut.strs << 'd'
|
169
|
+
@sut_clone.strs << 'e'
|
170
|
+
@sut_dup.strs << 'f'
|
171
|
+
|
172
|
+
_(@sut.strs).must_equal(%w[a b c d])
|
173
|
+
_(@sut_clone.strs).must_equal(%w[a b c e])
|
174
|
+
_(@sut_dup.strs).must_equal(%w[a b c f])
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'does not do a deep copy of the unsafe var' do
|
178
|
+
_(@sut.unsafe).wont_respond_to(:clone)
|
179
|
+
_(@sut.unsafe).wont_respond_to(:dup)
|
180
|
+
|
181
|
+
_(@sut.unsafe).must_be_same_as(@sut_clone.unsafe)
|
182
|
+
_(@sut.unsafe).must_be_same_as(@sut_dup.unsafe)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
class TestBag
|
188
|
+
include InitCopy::Able
|
189
|
+
|
190
|
+
attr_reader :orig
|
191
|
+
attr_reader :nums
|
192
|
+
|
193
|
+
def initialize
|
194
|
+
super
|
195
|
+
|
196
|
+
@__init_copy_method_name = nil
|
197
|
+
@orig = nil
|
198
|
+
@nums = [1,2,3]
|
199
|
+
end
|
200
|
+
|
201
|
+
def init_copy_method_name
|
202
|
+
return @__init_copy_method_name
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
class TestBagWithCopy < TestBag
|
207
|
+
protected
|
208
|
+
|
209
|
+
def init_copy(orig)
|
210
|
+
super
|
211
|
+
|
212
|
+
@orig = orig
|
213
|
+
@nums = ic_copy(@nums)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
class TestBagChildWithCopyAndUnsafe < TestBagWithCopy
|
218
|
+
attr_reader :strs
|
219
|
+
attr_reader :unsafe
|
220
|
+
|
221
|
+
def initialize
|
222
|
+
super
|
223
|
+
|
224
|
+
@strs = %w[a b c]
|
225
|
+
@unsafe = Class.new do
|
226
|
+
undef_method :clone
|
227
|
+
undef_method :dup
|
228
|
+
end.new
|
229
|
+
end
|
230
|
+
|
231
|
+
def init_copy(*)
|
232
|
+
super
|
233
|
+
|
234
|
+
@strs = ic_copy(@strs)
|
235
|
+
@unsafe = ic_copy?(@unsafe)
|
236
|
+
end
|
237
|
+
end
|
metadata
CHANGED
@@ -1,108 +1,67 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: init_copy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.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-09 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
|
+
- lib/init_copy/version.rb
|
30
|
+
- test/init_copy_test.rb
|
81
31
|
homepage: https://github.com/esotericpig/init_copy
|
82
32
|
licenses:
|
83
33
|
- MIT
|
84
34
|
metadata:
|
85
|
-
|
86
|
-
changelog_uri: https://github.com/esotericpig/init_copy/blob/master/CHANGELOG.md
|
35
|
+
rubygems_mfa_required: 'true'
|
87
36
|
homepage_uri: https://github.com/esotericpig/init_copy
|
88
37
|
source_code_uri: https://github.com/esotericpig/init_copy
|
89
|
-
|
90
|
-
|
38
|
+
bug_tracker_uri: https://github.com/esotericpig/init_copy/issues
|
39
|
+
changelog_uri: https://github.com/esotericpig/init_copy/blob/main/CHANGELOG.md
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options:
|
42
|
+
- "--embed-mixins"
|
43
|
+
- "--hyperlink-all"
|
44
|
+
- "--line-numbers"
|
45
|
+
- "--show-hash"
|
46
|
+
- "--main"
|
47
|
+
- README.md
|
48
|
+
- "--title"
|
49
|
+
- InitCopy v0.3.0
|
91
50
|
require_paths:
|
92
51
|
- lib
|
93
52
|
required_ruby_version: !ruby/object:Gem::Requirement
|
94
53
|
requirements:
|
95
54
|
- - ">="
|
96
55
|
- !ruby/object:Gem::Version
|
97
|
-
version: '
|
56
|
+
version: '3.1'
|
98
57
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
58
|
requirements:
|
100
59
|
- - ">="
|
101
60
|
- !ruby/object:Gem::Version
|
102
61
|
version: '0'
|
103
62
|
requirements: []
|
104
|
-
rubygems_version: 3.
|
105
|
-
signing_key:
|
63
|
+
rubygems_version: 3.5.21
|
64
|
+
signing_key:
|
106
65
|
specification_version: 4
|
107
|
-
summary: Easily use the
|
66
|
+
summary: Easily use the correct clone or dup method in initialize_copy.
|
108
67
|
test_files: []
|