init_copy 0.1.1 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f7a0940cd2260200b9b8d82c9e60a764c1ade5d3dd9311340b98453da4393cad
4
- data.tar.gz: 159371837bce7bf68ccc201af9da425daeeb86ef5c8a6ae4313ea365aba42f54
3
+ metadata.gz: 1620d2aa498e981be870fd3e0d671595b0407e557b54e40cf7e32b38b95158a8
4
+ data.tar.gz: 1b08062be47d208e59ed5a70e548f726d55936ccc000a84bbda5b2ed47119360
5
5
  SHA512:
6
- metadata.gz: f7c63f7f9303cfa625a31a90f202e0eeefade8edbcd083073868b0d96e7af8038beda13bc5731b8dc774c66fcf6eec1e5e3252c03655696eb6f27de929631567
7
- data.tar.gz: 7bbd82cb056013d14222cd064761148e5014362570f43f5b82142021199585a02b91a47e4513437f4637e0cbc221b2119e1ec59251aa4fe2fb2c4c05d881de6a
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
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2020 Jonathan Bradley Whited
3
+ Copyright (c) 2020-2025 Bradley Whited
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md ADDED
@@ -0,0 +1,162 @@
1
+ # InitCopy
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/init_copy.svg)](https://badge.fury.io/rb/init_copy)
4
+ [![CI Status](https://github.com/esotericpig/init_copy/actions/workflows/ci.yml/badge.svg)](https://github.com/esotericpig/init_copy/actions/workflows/ci.yml)
5
+
6
+ [![Source Code](https://img.shields.io/badge/source-github-%23211F1F.svg)](https://github.com/esotericpig/init_copy)
7
+ [![Changelog](https://img.shields.io/badge/changelog-md-%23A0522D.svg)](CHANGELOG.md)
8
+ [![License](https://img.shields.io/github/license/esotericpig/init_copy.svg)](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,51 +1,27 @@
1
1
  # encoding: UTF-8
2
2
  # frozen_string_literal: true
3
3
 
4
- #--
5
- # This file is part of InitCopy.
6
- # Copyright (c) 2020 Jonathan Bradley Whited (@esotericpig)
7
- #
8
- # InitCopy is free software: you can redistribute it and/or modify it under
9
- # the terms of the MIT License.
10
- #
11
- # You should have received a copy of the MIT License along with InitCopy.
12
- # If not, see <https://choosealicense.com/licenses/mit/>.
13
- #++
14
-
15
-
16
4
  require 'bundler/gem_tasks'
17
5
 
18
6
  require 'init_copy'
19
7
  require 'rake/clean'
20
8
  require 'rake/testtask'
21
- require 'yard'
22
-
9
+ require 'rdoc/task'
23
10
 
24
- CLEAN.exclude('.git/','stock/')
11
+ CLEAN.exclude('.git/','.github/','.idea/','stock/')
25
12
  CLOBBER.include('doc/')
26
13
 
14
+ task default: %i[test]
27
15
 
28
- task default: [:test]
29
-
30
- desc 'Generate doc (YARDoc)'
31
- task :doc => [:yard] do |task|
32
- end
33
-
34
- Rake::TestTask.new() do |task|
16
+ Rake::TestTask.new do |task|
35
17
  task.libs = ['lib','test']
36
- task.pattern = File.join('test','**','*_test.rb')
37
- task.description += ": '#{task.pattern}'"
18
+ task.pattern = 'test/**/*_test.rb'
19
+ task.options = '--pride'
38
20
  task.verbose = false
39
21
  task.warning = true
40
22
  end
41
23
 
42
- YARD::Rake::YardocTask.new() do |task|
43
- task.files = [File.join('lib','**','*.{rb}')]
44
-
45
- task.options += ['--files','CHANGELOG.md,LICENSE.txt']
46
- task.options += ['--readme','README.md']
47
-
48
- task.options << '--protected' # Show protected methods
49
- #task.options += ['--template-path',File.join('yard','templates')]
50
- 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}"
51
27
  end
data/init_copy.gemspec CHANGED
@@ -1,53 +1,45 @@
1
1
  # encoding: UTF-8
2
2
  # frozen_string_literal: true
3
3
 
4
- #--
5
- # This file is part of InitCopy.
6
- # Copyright (c) 2020 Jonathan Bradley Whited (@esotericpig)
7
- #
8
- # InitCopy is free software: you can redistribute it and/or modify it under
9
- # the terms of the MIT License.
10
- #
11
- # You should have received a copy of the MIT License along with InitCopy.
12
- # If not, see <https://choosealicense.com/licenses/mit/>.
13
- #++
4
+ require_relative 'lib/init_copy'
14
5
 
15
-
16
- lib = File.expand_path(File.join('..','lib'),__FILE__)
17
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
18
-
19
- require 'init_copy'
20
-
21
-
22
- Gem::Specification.new() do |spec|
6
+ Gem::Specification.new do |spec|
23
7
  spec.name = 'init_copy'
24
8
  spec.version = InitCopy::VERSION
25
- spec.authors = ['Jonathan Bradley Whited (@esotericpig)']
26
- spec.email = ['bradley@esotericpig.com']
9
+ spec.authors = ['Bradley Whited']
10
+ spec.email = ['code@esotericpig.com']
27
11
  spec.licenses = ['MIT']
28
12
  spec.homepage = 'https://github.com/esotericpig/init_copy'
29
- spec.summary = 'Easily use the appropriate clone/dup method in initialize_copy.'
13
+ spec.summary = 'Easily use the correct clone or dup method in initialize_copy.'
30
14
  spec.description = spec.summary
31
-
15
+
32
16
  spec.metadata = {
33
- 'bug_tracker_uri' => 'https://github.com/esotericpig/init_copy/issues',
34
- 'changelog_uri' => 'https://github.com/esotericpig/init_copy/blob/master/CHANGELOG.md',
35
- 'homepage_uri' => 'https://github.com/esotericpig/init_copy',
36
- 'source_code_uri' => 'https://github.com/esotericpig/init_copy'
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',
37
22
  }
38
-
39
- spec.require_paths = ['lib']
40
-
41
- spec.files = Dir.glob(File.join("{#{spec.require_paths.join(',')}}",'**','*.{rb}')) +
42
- %W( Gemfile #{spec.name}.gemspec Rakefile ) +
43
- %w( LICENSE.txt )
44
-
23
+
45
24
  # Lowest version that isn't eol (end-of-life).
46
25
  # - https://www.ruby-lang.org/en/downloads/branches/
47
- spec.required_ruby_version = '>= 2.4'
48
-
49
- spec.add_development_dependency 'bundler' ,'~> 2.1'
50
- spec.add_development_dependency 'minitest','~> 5.14'
51
- spec.add_development_dependency 'rake' ,'~> 13.0'
52
- spec.add_development_dependency 'yard' ,'~> 0.9' # For doc
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
53
45
  end
data/lib/init_copy.rb CHANGED
@@ -1,127 +1,79 @@
1
- #!/usr/bin/env ruby
2
1
  # encoding: UTF-8
3
2
  # frozen_string_literal: true
4
3
 
5
4
  #--
6
5
  # This file is part of InitCopy.
7
- # Copyright (c) 2020 Jonathan Bradley Whited (@esotericpig)
8
- #
9
- # InitCopy is free software: you can redistribute it and/or modify it under
10
- # the terms of the MIT License.
11
- #
12
- # You should have received a copy of the MIT License along with InitCopy.
13
- # If not, see <https://choosealicense.com/licenses/mit/>.
6
+ # Copyright (c) 2020 Bradley Whited
7
+ #
8
+ # SPDX-License-Identifier: MIT
14
9
  #++
15
10
 
16
-
17
- ###
18
- # @author Jonathan Bradley Whited (@esotericpig)
19
- # @since 0.1.0
20
- ###
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
21
26
  module InitCopy
22
- VERSION = '0.1.1'
23
-
24
- DEFAULT_COPY_NAME=:dup
25
-
26
- def self.new(default_name=DEFAULT_COPY_NAME)
27
- return Copier.new(default_name)
27
+ VERSION = '0.2.0'
28
+
29
+ def self.included(mod)
30
+ super
31
+
32
+ # NOTE: Can't use prepend(), else children's init_copy() won't call their parents', even with super().
33
+ mod.include(Copyable)
28
34
  end
29
-
30
- def self.find_copy_name(default_name=DEFAULT_COPY_NAME)
31
- copy_name = default_name
32
-
33
- caller.each() do |name|
34
- if name.end_with?(%q(clone'))
35
- copy_name = :clone
36
- break
37
- end
38
-
39
- if name.end_with?(%q(dup'))
40
- copy_name = :dup
41
- break
42
- end
43
- end
44
-
45
- return copy_name
35
+
36
+ def self.extended(mod)
37
+ super
38
+
39
+ mod.include(Copyable)
46
40
  end
47
-
48
- ###
49
- # @author Jonathan Bradley Whited (@esotericpig)
50
- # @since 0.1.0
51
- ###
52
- class Copier
53
- attr_accessor :default_name
54
- attr_accessor :name
55
-
56
- def initialize(default_name=DEFAULT_COPY_NAME)
57
- super()
58
-
59
- @default_name = default_name
60
-
61
- update_name()
62
- end
63
-
64
- def copy(var)
65
- return var.__send__(@name)
66
- end
67
-
68
- def safe_copy(var)
69
- return var.respond_to?(@name) ? var.__send__(@name) : var
70
- end
71
-
72
- def update_name()
73
- @name = InitCopy.find_copy_name(@default_name)
74
- end
41
+
42
+ def self.prepended(mod)
43
+ super
44
+
45
+ # User specifically requested to prepend.
46
+ mod.prepend(Copyable)
75
47
  end
76
-
77
- Copyer = Copier # Alias
78
-
79
- ###
80
- # The instance variable name is long and obnoxious to reduce conflicts.
81
- #
82
- # @author Jonathan Bradley Whited (@esotericpig)
83
- # @since 0.1.0
84
- ###
48
+
85
49
  module Copyable
86
- # @since 0.1.1
87
- def initialize(*)
88
- super
89
- @init_copy_method_name = DEFAULT_COPY_NAME
90
- end
91
-
92
- def initialize_clone(*)
93
- @init_copy_method_name = :clone
94
- super
95
- end
96
-
97
- def initialize_dup(*)
98
- @init_copy_method_name = :dup
50
+ def initialize_clone(orig)
99
51
  super
52
+
53
+ # The instance variable name is long & obnoxious to reduce conflicts.
54
+ @__init_copy_method_name = :clone
55
+ init_copy(orig)
100
56
  end
101
-
102
- def clone(*)
103
- @init_copy_method_name = :clone
57
+
58
+ def initialize_dup(orig)
104
59
  super
60
+
61
+ @__init_copy_method_name = :dup
62
+ init_copy(orig)
105
63
  end
106
-
107
- def dup(*)
108
- @init_copy_method_name = :dup
109
- super
64
+
65
+ protected
66
+
67
+ def init_copy(_orig)
110
68
  end
111
-
112
- private
113
-
114
- def copy(var)
115
- return var.__send__(@init_copy_method_name)
69
+
70
+ def ic_copy(var)
71
+ return var.__send__(@__init_copy_method_name)
116
72
  end
117
-
118
- def safe_copy(var)
119
- @init_copy_method_name = DEFAULT_COPY_NAME if @init_copy_method_name.nil?()
120
-
121
- return var.respond_to?(@init_copy_method_name) ?
122
- var.__send__(@init_copy_method_name) : var
73
+
74
+ def ic_copy?(var)
75
+ return var.__send__(@__init_copy_method_name) if var.respond_to?(@__init_copy_method_name)
76
+ return var
123
77
  end
124
78
  end
125
-
126
- Copiable = Copyable # Alias
127
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.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
- - Jonathan Bradley Whited (@esotericpig)
7
+ - Bradley Whited
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-07 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: bundler
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '2.1'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '2.1'
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
- - bradley@esotericpig.com
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
- bug_tracker_uri: https://github.com/esotericpig/init_copy/issues
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
37
+ bug_tracker_uri: https://github.com/esotericpig/init_copy/issues
38
+ changelog_uri: https://github.com/esotericpig/init_copy/blob/main/CHANGELOG.md
89
39
  post_install_message:
90
- rdoc_options: []
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.4'
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.1.2
62
+ rubygems_version: 3.5.21
105
63
  signing_key:
106
64
  specification_version: 4
107
- summary: Easily use the appropriate clone/dup method in initialize_copy.
65
+ summary: Easily use the correct clone or dup method in initialize_copy.
108
66
  test_files: []