core-state 0.1.8 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bc77a1d51f01d64addaf2f51e786ebd3fb34e3b872a93b77784b7b37d4ae215e
4
- data.tar.gz: 6bdf81604e1630610ba65165b555f297f51b2939babadd7758048a40cce60771
3
+ metadata.gz: 477f7141fabe96eb7a23f595f9577e672e371e985dd986120ed3310d302ed95a
4
+ data.tar.gz: 032c9fdaa012fb0f5fed35817d23aa693944005f1254deeb3a87e10e73c130e0
5
5
  SHA512:
6
- metadata.gz: 4ccc3ca6537fb926e2dd91471911299ed279bc6e9d675d1792afe5ec8abdbffeff768c6f4ec938658b262a33e90737ce371b2a59d62f56a2ea5411dafd355c38
7
- data.tar.gz: b10328010f5089ab9d38491b3231301d62ea1e87788d730ae67b1e4fb3ff9523c1829c214c2a7911bbd466845e72d3d073cc7c2649d403549c529b19e0211e35
6
+ metadata.gz: 3e44fde7c140c8268b51ee49d182f4240ab231ec8129fa57e9c11d97a3f915aca5ba376074eeb56ae11942293bda67007efb379501d0ab28c810aea658efe6ad
7
+ data.tar.gz: 931bf990e70cfb5e28975229ed0d8168e6efc324c786fa7d572b75a07a82fd7ee21e747ca7c46e3e166cd8e6b402775470261e82a22a7323b72f1e3412cfec28
data/CHANGELOG.md CHANGED
@@ -1,57 +1,64 @@
1
- ## [v0.1.8](https://github.com/metabahn/corerb/releases/tag/2023-05-07)
1
+ ## [v0.2.0](https://github.com/bryanp/corerb/releases/tag/2023-12-24)
2
+
3
+ *released on 2023-12-24*
4
+
5
+ * `dep` [#143](https://github.com/bryanp/corerb/pull/143) Deprecate `Is::*` and `Refine::*` namespaces ([bryanp](https://github.com/bryanp))
6
+ * `dep` [#135](https://github.com/bryanp/corerb/pull/135) Remove Ruby 2 support ([bryanp](https://github.com/bryanp))
7
+
8
+ ## [v0.1.8](https://github.com/bryanp/corerb/releases/tag/2023-05-07)
2
9
 
3
10
  *released on 2023-05-07*
4
11
 
5
12
  * `fix` [#132](https://github.com/bryanp/corerb/pull/132) Fix state inheritence ([bryanp](https://github.com/bryanp))
6
13
 
7
- ## [v0.1.7](https://github.com/metabahn/corerb/releases/tag/2021-11-23.1)
14
+ ## [v0.1.7](https://github.com/bryanp/corerb/releases/tag/2021-11-23.1)
8
15
 
9
16
  *released on 2021-11-23*
10
17
 
11
- * `chg` [#109](https://github.com/metabahn/corerb/pull/109) Prefer `__send__` to `send` ([bryanp](https://github.com/bryanp))
18
+ * `chg` [#109](https://github.com/bryanp/corerb/pull/109) Prefer `__send__` to `send` ([bryanp](https://github.com/bryanp))
12
19
 
13
- ## [v0.1.6](https://github.com/metabahn/corerb/releases/tag/2021-11-02)
20
+ ## [v0.1.6](https://github.com/bryanp/corerb/releases/tag/2021-11-02)
14
21
 
15
22
  *released on 2021-11-02*
16
23
 
17
- * `chg` [#97](https://github.com/metabahn/corerb/pull/97) Designate internal state with leading and trailing double underscores ([bryanp](https://github.com/bryanp))
24
+ * `chg` [#97](https://github.com/bryanp/corerb/pull/97) Designate internal state with leading and trailing double underscores ([bryanp](https://github.com/bryanp))
18
25
 
19
- ## [v0.1.5](https://github.com/metabahn/corerb/releases/tag/2021-10-22)
26
+ ## [v0.1.5](https://github.com/bryanp/corerb/releases/tag/2021-10-22)
20
27
 
21
28
  *released on 2021-10-22*
22
29
 
23
- * `fix` [#88](https://github.com/metabahn/corerb/pull/88) Fix an issue causing state to be shared between sibling subclasses ([bryanp](https://github.com/bryanp))
30
+ * `fix` [#88](https://github.com/bryanp/corerb/pull/88) Fix an issue causing state to be shared between sibling subclasses ([bryanp](https://github.com/bryanp))
24
31
 
25
- ## [v0.1.4](https://github.com/metabahn/corerb/releases/tag/2021-09-30)
32
+ ## [v0.1.4](https://github.com/bryanp/corerb/releases/tag/2021-09-30)
26
33
 
27
34
  *released on 2021-09-30*
28
35
 
29
- * `fix` [#85](https://github.com/metabahn/corerb/pull/85) Initialize with class-level state when available ([bryanp](https://github.com/bryanp))
36
+ * `fix` [#85](https://github.com/bryanp/corerb/pull/85) Initialize with class-level state when available ([bryanp](https://github.com/bryanp))
30
37
 
31
- ## [v0.1.3](https://github.com/metabahn/corerb/releases/tag/2021-09-28)
38
+ ## [v0.1.3](https://github.com/bryanp/corerb/releases/tag/2021-09-28)
32
39
 
33
40
  *released on 2021-09-28*
34
41
 
35
- * `fix` [#84](https://github.com/metabahn/corerb/pull/84) Define core-local as a dependency of core-state ([bryanp](https://github.com/bryanp))
42
+ * `fix` [#84](https://github.com/bryanp/corerb/pull/84) Define core-local as a dependency of core-state ([bryanp](https://github.com/bryanp))
36
43
 
37
- ## [v0.1.1](https://github.com/metabahn/corerb/releases/tag/2021-07-15)
44
+ ## [v0.1.1](https://github.com/bryanp/corerb/releases/tag/2021-07-15)
38
45
 
39
46
  *released on 2021-07-15*
40
47
 
41
- * `fix` [#62](https://github.com/metabahn/corerb/pull/62) Correctly isolate class-level state on access ([bryanp](https://github.com/bryanp))
42
- * `fix` [#55](https://github.com/metabahn/corerb/pull/55) Correctly forward arguments to super initialize ([bryanp](https://github.com/bryanp))
48
+ * `fix` [#62](https://github.com/bryanp/corerb/pull/62) Correctly isolate class-level state on access ([bryanp](https://github.com/bryanp))
49
+ * `fix` [#55](https://github.com/bryanp/corerb/pull/55) Correctly forward arguments to super initialize ([bryanp](https://github.com/bryanp))
43
50
 
44
- ## [v0.1.0](https://github.com/metabahn/corerb/releases/tag/2021-07-07)
51
+ ## [v0.1.0](https://github.com/bryanp/corerb/releases/tag/2021-07-07)
45
52
 
46
53
  *released on 2021-07-07*
47
54
 
48
- * `fix` [#48](https://github.com/metabahn/corerb/pull/48) Correctly copy defined state when a stateful object is copied ([bryanp](https://github.com/bryanp))
49
- * `chg` [#44](https://github.com/metabahn/corerb/pull/44) Drop Ruby 2.6 support from core-state ([bryanp](https://github.com/bryanp))
55
+ * `fix` [#48](https://github.com/bryanp/corerb/pull/48) Correctly copy defined state when a stateful object is copied ([bryanp](https://github.com/bryanp))
56
+ * `chg` [#44](https://github.com/bryanp/corerb/pull/44) Drop Ruby 2.6 support from core-state ([bryanp](https://github.com/bryanp))
50
57
 
51
- ## [v0.0.0](https://github.com/metabahn/corerb/releases/tag/2021-05-22)
58
+ ## [v0.0.0](https://github.com/bryanp/corerb/releases/tag/2021-05-22)
52
59
 
53
60
  *released on 2021-05-22*
54
61
 
55
- * `add` [#31](https://github.com/metabahn/corerb/pull/31) Initial implementation of core-state ([bryanp](https://github.com/bryanp))
62
+ * `add` [#31](https://github.com/bryanp/corerb/pull/31) Initial implementation of core-state ([bryanp](https://github.com/bryanp))
56
63
 
57
64
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Core
4
4
  module State
5
- VERSION = "0.1.8"
5
+ VERSION = "0.2.0"
6
6
 
7
7
  def self.version
8
8
  VERSION
data/lib/core/state.rb CHANGED
@@ -1,9 +1,233 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "core/copy"
4
+ require "core/extension"
5
+ require "core/local"
6
+
3
7
  module Core
8
+ # [public] Make objects stateful.
9
+ #
4
10
  module State
5
11
  require_relative "state/version"
12
+
13
+ extend Core::Extension
14
+
15
+ using Core::Copy
16
+
17
+ ALLOWED_FLAGS = %i[class instance].freeze
18
+
19
+ applies do
20
+ prepend_defined_state_modules
21
+ end
22
+
23
+ extends :definition do
24
+ # [public] Defines state by name.
25
+ #
26
+ # flags - Changes how the state is defined. Possible values include:
27
+ #
28
+ # * `:class` - Defines state at the class level.
29
+ #
30
+ # * `:instance` - Defines state at the instance level.
31
+ #
32
+ # Dependencies are applied with both the `:class` and `:instance` flags by default.
33
+ #
34
+ # default - The default value for the defined state.
35
+ #
36
+ # private - If `true`, the reader/writer will be defined as private.
37
+ #
38
+ # reader - If `true`, defines a reader for the state.
39
+ #
40
+ # writer - If `true`, defines a reader for the state.
41
+ #
42
+ def state(name, *flags, default: nil, private: false, reader: true, writer: true)
43
+ flags = flags.map(&:to_sym)
44
+ enforce_allowed_flags(flags)
45
+
46
+ state = {
47
+ value: default,
48
+ class: define_class_state?(flags),
49
+ instance: define_instance_state?(flags)
50
+ }
51
+
52
+ method_name = name.to_sym
53
+ ivar_name = "@#{method_name}"
54
+ defined_state[ivar_name] = state
55
+ defined_state_isolations << ivar_name
56
+
57
+ if state[:class]
58
+ instance_variable_set(ivar_name, default)
59
+ end
60
+
61
+ prefix = if private
62
+ "private "
63
+ else
64
+ ""
65
+ end
66
+
67
+ if reader
68
+ if state[:class]
69
+ defined_state_class_module.module_eval <<~CODE, __FILE__, __LINE__ + 1
70
+ #{prefix}def #{method_name}
71
+ unless defined_state_isolations.include?(#{ivar_name.inspect})
72
+ #{ivar_name} = #{ivar_name}.copy
73
+ defined_state_isolations << #{ivar_name.inspect}
74
+ end
75
+
76
+ #{ivar_name}
77
+ end
78
+ CODE
79
+ end
80
+
81
+ if state[:instance]
82
+ defined_state_instance_module.module_eval <<~CODE, __FILE__, __LINE__ + 1
83
+ #{prefix}def #{method_name}
84
+ unless defined_state_isolations.include?(#{ivar_name.inspect})
85
+ #{ivar_name} = #{ivar_name}.copy
86
+ defined_state_isolations << #{ivar_name.inspect}
87
+ end
88
+
89
+ #{ivar_name}
90
+ end
91
+ CODE
92
+ end
93
+ end
94
+
95
+ if writer
96
+ if state[:class]
97
+ defined_state_class_module.module_eval <<~CODE, __FILE__, __LINE__ + 1
98
+ #{prefix}def #{method_name}=(value)
99
+ defined_state[#{ivar_name.inspect}][:value] = value
100
+ #{ivar_name} = value
101
+ end
102
+ CODE
103
+ end
104
+
105
+ if state[:instance]
106
+ defined_state_instance_module.module_eval <<~CODE, __FILE__, __LINE__ + 1
107
+ #{prefix}def #{method_name}=(value)
108
+ #{ivar_name} = value
109
+ end
110
+ CODE
111
+ end
112
+ end
113
+
114
+ if state[:class]
115
+ instance_variable_set(ivar_name, default)
116
+ end
117
+ end
118
+
119
+ def inherited(subclass)
120
+ defined_state.each_pair do |name, state|
121
+ if state[:class]
122
+ subclass.instance_variable_set(name, instance_variable_get(name))
123
+ end
124
+ end
125
+
126
+ subclass.__send__(:prepend_defined_state_modules)
127
+ subclass.instance_variable_set(:@__defined_state__, @__defined_state__.each_with_object({}) { |(key, value), state|
128
+ state[key] = value.dup
129
+ })
130
+
131
+ super
132
+ end
133
+
134
+ private def defined_state
135
+ @__defined_state__ ||= {}
136
+ end
137
+
138
+ private def defined_state_class_module
139
+ @__defined_state_class_module__ ||= Module.new
140
+ end
141
+
142
+ private def defined_state_instance_module
143
+ @__defined_state_instance_module__ ||= Module.new
144
+ end
145
+
146
+ private def prepend_defined_state_modules
147
+ prepend(defined_state_instance_module)
148
+ singleton_class.prepend(defined_state_class_module)
149
+ end
150
+
151
+ private def enforce_allowed_flags(flags)
152
+ flags.each do |flag|
153
+ unless allowed_flag?(flag)
154
+ raise ArgumentError, "Expected flag `#{flag.inspect}' to be one of: #{allowed_flags_string}"
155
+ end
156
+ end
157
+ end
158
+
159
+ private def allowed_flag?(flag)
160
+ ALLOWED_FLAGS.include?(flag)
161
+ end
162
+
163
+ private def allowed_flags_string
164
+ ALLOWED_FLAGS.map { |allowed_flag|
165
+ "`#{allowed_flag.inspect}'"
166
+ }.join(", ")
167
+ end
168
+
169
+ private def define_class_state?(flags)
170
+ flags.empty? || flags.include?(:class)
171
+ end
172
+
173
+ private def define_instance_state?(flags)
174
+ flags.empty? || flags.include?(:instance)
175
+ end
176
+ end
177
+
178
+ extends :implementation, prepend: true do
179
+ def initialize(...)
180
+ self_class = self.class
181
+ self_class.__send__(:defined_state).each_pair do |name, state|
182
+ if state[:instance]
183
+ if state[:class]
184
+ instance_variable_set(name, self_class.instance_variable_get(name))
185
+ else
186
+ instance_variable_set(name, state[:value])
187
+ end
188
+ end
189
+ end
190
+
191
+ super
192
+ end
193
+
194
+ def initialize_copy(...)
195
+ @__defined_state_isolations__ = []
196
+
197
+ super
198
+ end
199
+ end
200
+
201
+ extends :definition, :implementation do
202
+ # [public] Safely mutates state by name, yielding a copy of the current value to the block.
203
+ #
204
+ def mutate_state(name, &block)
205
+ __send__("#{name}=", block.call(__send__(name)))
206
+ end
207
+
208
+ private def defined_state_isolations
209
+ @__defined_state_isolations__ ||= []
210
+ end
211
+ end
212
+
213
+ class << self
214
+ include Core::Local
215
+
216
+ def prevent_recursion(object)
217
+ object_id = object.object_id
218
+ copied_objects[object_id] = true
219
+ yield
220
+ ensure
221
+ copied_objects.delete(object_id)
222
+ end
223
+
224
+ def copying?(object)
225
+ copied_objects[object.object_id]
226
+ end
227
+
228
+ def copied_objects
229
+ localized(:__corerb_copied_objects) || localize(:__corerb_copied_objects, {})
230
+ end
231
+ end
6
232
  end
7
233
  end
8
-
9
- require_relative "../is/stateful"
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: core-state
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.8
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bryan Powell
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-05-08 00:00:00.000000000 Z
11
+ date: 2023-12-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: core-extension
14
+ name: core-copy
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
@@ -24,22 +24,36 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: core-extension
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.5'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.5'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: core-local
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
45
  - - "~>"
32
46
  - !ruby/object:Gem::Version
33
- version: '0.1'
47
+ version: '0.2'
34
48
  type: :runtime
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
52
  - - "~>"
39
53
  - !ruby/object:Gem::Version
40
- version: '0.1'
54
+ version: '0.2'
41
55
  description: Easily manage object state.
42
- email: bryan@metabahn.com
56
+ email: bryan@bryanp.org
43
57
  executables: []
44
58
  extensions: []
45
59
  extra_rdoc_files: []
@@ -48,8 +62,7 @@ files:
48
62
  - LICENSE
49
63
  - lib/core/state.rb
50
64
  - lib/core/state/version.rb
51
- - lib/is/stateful.rb
52
- homepage: https://github.com/metabahn/corerb/
65
+ homepage: https://github.com/bryanp/corerb/
53
66
  licenses:
54
67
  - MPL-2.0
55
68
  metadata: {}
@@ -61,14 +74,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
61
74
  requirements:
62
75
  - - ">="
63
76
  - !ruby/object:Gem::Version
64
- version: '2.7'
77
+ version: '3.0'
65
78
  required_rubygems_version: !ruby/object:Gem::Requirement
66
79
  requirements:
67
80
  - - ">="
68
81
  - !ruby/object:Gem::Version
69
82
  version: '0'
70
83
  requirements: []
71
- rubygems_version: 3.4.12
84
+ rubygems_version: 3.5.1
72
85
  signing_key:
73
86
  specification_version: 4
74
87
  summary: Easily manage object state.
data/lib/is/stateful.rb DELETED
@@ -1,295 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "core/extension"
4
- require "core/local"
5
-
6
- module Is
7
- # [public] Makes objects stateful.
8
- #
9
- module Stateful
10
- # Adding core-copy as a dependency creates a recursive dependency, so just bundle it.
11
- #
12
- module Copy
13
- DEFAULT = ::Object.new
14
-
15
- refine ::Object do
16
- if RbConfig::CONFIG["RUBY_PROGRAM_VERSION"] < "3"
17
- def copy(freeze: DEFAULT)
18
- should_freeze = resolve_freeze_argument(freeze)
19
-
20
- value = clone(freeze: should_freeze)
21
- value.freeze if should_freeze
22
- value
23
- end
24
- else
25
- def copy(freeze: DEFAULT)
26
- clone(freeze: resolve_freeze_argument(freeze))
27
- end
28
- end
29
-
30
- private def resolve_freeze_argument(value)
31
- case value
32
- when DEFAULT
33
- frozen?
34
- else
35
- !!value
36
- end
37
- end
38
- end
39
-
40
- refine Array do
41
- def copy(freeze: DEFAULT)
42
- unless Stateful.copying?(self)
43
- Stateful.prevent_recursion(self) do
44
- array = map { |value|
45
- value.copy(freeze: freeze)
46
- }
47
-
48
- array.freeze if resolve_freeze_argument(freeze)
49
-
50
- array
51
- end
52
- end
53
- end
54
- end
55
-
56
- refine Hash do
57
- def copy(freeze: DEFAULT)
58
- unless Stateful.copying?(self)
59
- Stateful.prevent_recursion(self) do
60
- hash = {}
61
-
62
- each_pair do |key, value|
63
- hash[key.copy(freeze: freeze)] = value.copy(freeze: freeze)
64
- end
65
-
66
- hash.freeze if resolve_freeze_argument(freeze)
67
-
68
- hash
69
- end
70
- end
71
- end
72
- end
73
- end
74
-
75
- extend Is::Extension
76
-
77
- using Copy
78
-
79
- ALLOWED_FLAGS = %i[class instance].freeze
80
-
81
- applies do
82
- prepend_defined_state_modules
83
- end
84
-
85
- extends :definition do
86
- # [public] Defines state by name.
87
- #
88
- # flags - Changes how the state is defined. Possible values include:
89
- #
90
- # * `:class` - Defines state at the class level.
91
- #
92
- # * `:instance` - Defines state at the instance level.
93
- #
94
- # Dependencies are applied with both the `:class` and `:instance` flags by default.
95
- #
96
- # default - The default value for the defined state.
97
- #
98
- # private - If `true`, the reader/writer will be defined as private.
99
- #
100
- # reader - If `true`, defines a reader for the state.
101
- #
102
- # writer - If `true`, defines a reader for the state.
103
- #
104
- def state(name, *flags, default: nil, private: false, reader: true, writer: true)
105
- flags = flags.map(&:to_sym)
106
- enforce_allowed_flags(flags)
107
-
108
- state = {
109
- value: default,
110
- class: define_class_state?(flags),
111
- instance: define_instance_state?(flags)
112
- }
113
-
114
- method_name = name.to_sym
115
- ivar_name = "@#{method_name}"
116
- defined_state[ivar_name] = state
117
- defined_state_isolations << ivar_name
118
-
119
- if state[:class]
120
- instance_variable_set(ivar_name, default)
121
- end
122
-
123
- prefix = if private
124
- "private "
125
- else
126
- ""
127
- end
128
-
129
- if reader
130
- if state[:class]
131
- defined_state_class_module.module_eval <<~CODE, __FILE__, __LINE__ + 1
132
- #{prefix}def #{method_name}
133
- unless defined_state_isolations.include?(#{ivar_name.inspect})
134
- #{ivar_name} = #{ivar_name}.copy
135
- defined_state_isolations << #{ivar_name.inspect}
136
- end
137
-
138
- #{ivar_name}
139
- end
140
- CODE
141
- end
142
-
143
- if state[:instance]
144
- defined_state_instance_module.module_eval <<~CODE, __FILE__, __LINE__ + 1
145
- #{prefix}def #{method_name}
146
- unless defined_state_isolations.include?(#{ivar_name.inspect})
147
- #{ivar_name} = #{ivar_name}.copy
148
- defined_state_isolations << #{ivar_name.inspect}
149
- end
150
-
151
- #{ivar_name}
152
- end
153
- CODE
154
- end
155
- end
156
-
157
- if writer
158
- if state[:class]
159
- defined_state_class_module.module_eval <<~CODE, __FILE__, __LINE__ + 1
160
- #{prefix}def #{method_name}=(value)
161
- defined_state[#{ivar_name.inspect}][:value] = value
162
- #{ivar_name} = value
163
- end
164
- CODE
165
- end
166
-
167
- if state[:instance]
168
- defined_state_instance_module.module_eval <<~CODE, __FILE__, __LINE__ + 1
169
- #{prefix}def #{method_name}=(value)
170
- #{ivar_name} = value
171
- end
172
- CODE
173
- end
174
- end
175
-
176
- if state[:class]
177
- instance_variable_set(ivar_name, default)
178
- end
179
- end
180
-
181
- def inherited(subclass)
182
- defined_state.each_pair do |name, state|
183
- if state[:class]
184
- subclass.instance_variable_set(name, instance_variable_get(name))
185
- end
186
- end
187
-
188
- subclass.__send__(:prepend_defined_state_modules)
189
- subclass.instance_variable_set(:@__defined_state__, @__defined_state__.each_with_object({}) { |(key, value), state|
190
- state[key] = value.dup
191
- })
192
-
193
- super
194
- end
195
-
196
- private def defined_state
197
- @__defined_state__ ||= {}
198
- end
199
-
200
- private def defined_state_class_module
201
- @__defined_state_class_module__ ||= Module.new
202
- end
203
-
204
- private def defined_state_instance_module
205
- @__defined_state_instance_module__ ||= Module.new
206
- end
207
-
208
- private def prepend_defined_state_modules
209
- prepend(defined_state_instance_module)
210
- singleton_class.prepend(defined_state_class_module)
211
- end
212
-
213
- private def enforce_allowed_flags(flags)
214
- flags.each do |flag|
215
- unless allowed_flag?(flag)
216
- raise ArgumentError, "Expected flag `#{flag.inspect}' to be one of: #{allowed_flags_string}"
217
- end
218
- end
219
- end
220
-
221
- private def allowed_flag?(flag)
222
- ALLOWED_FLAGS.include?(flag)
223
- end
224
-
225
- private def allowed_flags_string
226
- ALLOWED_FLAGS.map { |allowed_flag|
227
- "`#{allowed_flag.inspect}'"
228
- }.join(", ")
229
- end
230
-
231
- private def define_class_state?(flags)
232
- flags.empty? || flags.include?(:class)
233
- end
234
-
235
- private def define_instance_state?(flags)
236
- flags.empty? || flags.include?(:instance)
237
- end
238
- end
239
-
240
- extends :implementation, prepend: true do
241
- def initialize(...)
242
- self_class = self.class
243
- self_class.__send__(:defined_state).each_pair do |name, state|
244
- if state[:instance]
245
- if state[:class]
246
- instance_variable_set(name, self_class.instance_variable_get(name))
247
- else
248
- instance_variable_set(name, state[:value])
249
- end
250
- end
251
- end
252
-
253
- super
254
- end
255
-
256
- def initialize_copy(...)
257
- @__defined_state_isolations__ = []
258
-
259
- super
260
- end
261
- end
262
-
263
- extends :definition, :implementation do
264
- # [public] Safely mutates state by name, yielding a copy of the current value to the block.
265
- #
266
- def mutate_state(name, &block)
267
- __send__("#{name}=", block.call(__send__(name)))
268
- end
269
-
270
- private def defined_state_isolations
271
- @__defined_state_isolations__ ||= []
272
- end
273
- end
274
-
275
- class << self
276
- include Is::Localized
277
-
278
- def prevent_recursion(object)
279
- object_id = object.object_id
280
- copied_objects[object_id] = true
281
- yield
282
- ensure
283
- copied_objects.delete(object_id)
284
- end
285
-
286
- def copying?(object)
287
- copied_objects[object.object_id]
288
- end
289
-
290
- def copied_objects
291
- localized(:__corerb_copied_objects) || localize(:__corerb_copied_objects, {})
292
- end
293
- end
294
- end
295
- end