qonfig 0.12.0 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +457 -137
- data/lib/qonfig/command_set.rb +7 -1
- data/lib/qonfig/commands/add_nested_option.rb +3 -1
- data/lib/qonfig/commands/add_option.rb +2 -1
- data/lib/qonfig/commands/base.rb +2 -1
- data/lib/qonfig/commands/compose.rb +16 -10
- data/lib/qonfig/commands/expose_yaml.rb +2 -1
- data/lib/qonfig/commands/load_from_env.rb +2 -1
- data/lib/qonfig/commands/load_from_json.rb +2 -1
- data/lib/qonfig/commands/load_from_self.rb +2 -1
- data/lib/qonfig/commands/load_from_yaml.rb +2 -1
- data/lib/qonfig/data_set/lock.rb +46 -0
- data/lib/qonfig/data_set.rb +92 -23
- data/lib/qonfig/errors.rb +8 -0
- data/lib/qonfig/plugins/toml/commands/expose_toml.rb +2 -1
- data/lib/qonfig/plugins/toml/commands/load_from_toml.rb +2 -1
- data/lib/qonfig/settings/builder.rb +20 -4
- data/lib/qonfig/settings/callbacks.rb +43 -0
- data/lib/qonfig/settings/key_matcher.rb +175 -0
- data/lib/qonfig/settings/lock.rb +3 -3
- data/lib/qonfig/settings.rb +144 -33
- data/lib/qonfig/validator/basic.rb +53 -0
- data/lib/qonfig/validator/builder/attribute_consistency.rb +181 -0
- data/lib/qonfig/validator/builder.rb +169 -0
- data/lib/qonfig/validator/collection.rb +73 -0
- data/lib/qonfig/validator/dsl.rb +51 -0
- data/lib/qonfig/validator/method_based.rb +49 -0
- data/lib/qonfig/validator/predefined/common.rb +53 -0
- data/lib/qonfig/validator/predefined/registry.rb +83 -0
- data/lib/qonfig/validator/predefined/registry_control_mixin.rb +43 -0
- data/lib/qonfig/validator/predefined.rb +41 -0
- data/lib/qonfig/validator/proc_based.rb +53 -0
- data/lib/qonfig/validator.rb +58 -0
- data/lib/qonfig/version.rb +1 -1
- data/lib/qonfig.rb +1 -0
- data/qonfig.gemspec +1 -1
- metadata +19 -5
- data/lib/qonfig/data_set/validator.rb +0 -7
@@ -32,14 +32,16 @@ class Qonfig::Commands::AddNestedOption < Qonfig::Commands::Base
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
+
# @param data_set [Qonfig::DataSet]
|
35
36
|
# @param settings [Qonfig::Settings]
|
36
37
|
# @return [void]
|
37
38
|
#
|
38
39
|
# @api private
|
39
40
|
# @since 0.1.0
|
40
|
-
def call(settings)
|
41
|
+
def call(data_set, settings)
|
41
42
|
nested_settings = nested_data_set_klass.new.settings
|
42
43
|
|
44
|
+
nested_settings.__mutation_callbacks__.add(settings.__mutation_callbacks__)
|
43
45
|
settings.__define_setting__(key, nested_settings)
|
44
46
|
end
|
45
47
|
end
|
@@ -30,12 +30,13 @@ class Qonfig::Commands::AddOption < Qonfig::Commands::Base
|
|
30
30
|
@value = value
|
31
31
|
end
|
32
32
|
|
33
|
+
# @param data_set [Qonfig::DataSet]
|
33
34
|
# @param settings [Qonfig::Settings]
|
34
35
|
# @return [void]
|
35
36
|
#
|
36
37
|
# @api private
|
37
38
|
# @since 0.1.0
|
38
|
-
def call(settings)
|
39
|
+
def call(data_set, settings)
|
39
40
|
settings.__define_setting__(key, value)
|
40
41
|
end
|
41
42
|
end
|
data/lib/qonfig/commands/base.rb
CHANGED
@@ -3,10 +3,11 @@
|
|
3
3
|
# @api private
|
4
4
|
# @since 0.1.0
|
5
5
|
class Qonfig::Commands::Base
|
6
|
+
# @param data_set [Qonfig::DataSet]
|
6
7
|
# @param settings [Qonfig::Settings]
|
7
8
|
# @return [void]
|
8
9
|
#
|
9
10
|
# @api private
|
10
11
|
# @since 0.1.0
|
11
|
-
def call(settings); end
|
12
|
+
def call(data_set, settings); end
|
12
13
|
end
|
@@ -7,31 +7,37 @@ class Qonfig::Commands::Compose < Qonfig::Commands::Base
|
|
7
7
|
#
|
8
8
|
# @api private
|
9
9
|
# @since 0.1.0
|
10
|
-
attr_reader :
|
10
|
+
attr_reader :composable_data_set_klass
|
11
11
|
|
12
|
-
# @param
|
12
|
+
# @param composable_data_set_klass [Qonfig::DataSet]
|
13
13
|
#
|
14
14
|
# @raise [Qonfig::ArgumentError]
|
15
15
|
#
|
16
16
|
# @api private
|
17
17
|
# @since 0.1.0
|
18
|
-
def initialize(
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
18
|
+
def initialize(composable_data_set_klass)
|
19
|
+
unless composable_data_set_klass.is_a?(Class) && composable_data_set_klass < Qonfig::DataSet
|
20
|
+
raise(
|
21
|
+
Qonfig::ArgumentError,
|
22
|
+
'Composed config class should be a subtype of Qonfig::DataSet'
|
23
|
+
)
|
24
|
+
end
|
23
25
|
|
24
|
-
@
|
26
|
+
@composable_data_set_klass = composable_data_set_klass
|
25
27
|
end
|
26
28
|
|
29
|
+
# @param data_set [Qonfig::DataSet]
|
27
30
|
# @param settings [Qonfig::Settings]
|
28
31
|
# @return [void]
|
29
32
|
#
|
30
33
|
# @api private
|
31
34
|
# @since 0.1.0
|
32
|
-
def call(settings)
|
33
|
-
|
35
|
+
def call(data_set, settings)
|
36
|
+
# NOTE: append new validators
|
37
|
+
data_set.class.validators.concat(composable_data_set_klass.validators.dup)
|
34
38
|
|
39
|
+
# NOTE: append new settings
|
40
|
+
composite_settings = composable_data_set_klass.new.settings
|
35
41
|
settings.__append_settings__(composite_settings)
|
36
42
|
end
|
37
43
|
end
|
@@ -60,12 +60,13 @@ class Qonfig::Commands::ExposeYAML < Qonfig::Commands::Base
|
|
60
60
|
@env = env
|
61
61
|
end
|
62
62
|
|
63
|
+
# @param data_set [Qonfig::DataSet]
|
63
64
|
# @param settings [Qonfig::Settings]
|
64
65
|
# @return [void]
|
65
66
|
#
|
66
67
|
# @api private
|
67
68
|
# @since 0.7.0
|
68
|
-
def call(settings)
|
69
|
+
def call(data_set, settings)
|
69
70
|
case via
|
70
71
|
when EXPOSERS[:file_name]
|
71
72
|
expose_file_name!(settings)
|
@@ -55,12 +55,13 @@ class Qonfig::Commands::LoadFromENV < Qonfig::Commands::Base
|
|
55
55
|
@trim_pattern = prefix.is_a?(Regexp) ? prefix : /\A(#{Regexp.escape(prefix.to_s)})/m
|
56
56
|
end
|
57
57
|
|
58
|
+
# @param data_set [Qonfig::DataSet]
|
58
59
|
# @param settings [Qonfig::Settings]
|
59
60
|
# @return [void]
|
60
61
|
#
|
61
62
|
# @api private
|
62
63
|
# @since 0.2.0
|
63
|
-
def call(settings)
|
64
|
+
def call(data_set, settings)
|
64
65
|
env_data = extract_env_data
|
65
66
|
|
66
67
|
env_based_settings = build_data_set_class(env_data).new.settings
|
@@ -25,12 +25,13 @@ class Qonfig::Commands::LoadFromJSON < Qonfig::Commands::Base
|
|
25
25
|
@strict = strict
|
26
26
|
end
|
27
27
|
|
28
|
+
# @param data_set [Qonfig::DataSet]
|
28
29
|
# @param settings [Qonfig::Settings]
|
29
30
|
# @return [void]
|
30
31
|
#
|
31
32
|
# @api private
|
32
33
|
# @since 0.5.0
|
33
|
-
def call(settings)
|
34
|
+
def call(data_set, settings)
|
34
35
|
json_data = Qonfig::Loaders::JSON.load_file(file_path, fail_on_unexist: strict)
|
35
36
|
|
36
37
|
raise(
|
@@ -17,12 +17,13 @@ class Qonfig::Commands::LoadFromSelf < Qonfig::Commands::Base
|
|
17
17
|
@caller_location = caller_location
|
18
18
|
end
|
19
19
|
|
20
|
+
# @param data_set [Qonfig::DataSet]
|
20
21
|
# @param settings [Qonfig::Settings]
|
21
22
|
# @return [void]
|
22
23
|
#
|
23
24
|
# @api private
|
24
25
|
# @since 0.2.0
|
25
|
-
def call(settings)
|
26
|
+
def call(data_set, settings)
|
26
27
|
yaml_data = load_self_placed_yaml_data
|
27
28
|
|
28
29
|
yaml_based_settings = build_data_set_klass(yaml_data).new.settings
|
@@ -25,6 +25,7 @@ class Qonfig::Commands::LoadFromYAML < Qonfig::Commands::Base
|
|
25
25
|
@strict = strict
|
26
26
|
end
|
27
27
|
|
28
|
+
# @param data_set [Qonfig::DataSet]
|
28
29
|
# @param settings [Qonfig::Settings]
|
29
30
|
# @return [void]
|
30
31
|
#
|
@@ -32,7 +33,7 @@ class Qonfig::Commands::LoadFromYAML < Qonfig::Commands::Base
|
|
32
33
|
#
|
33
34
|
# @api private
|
34
35
|
# @since 0.2.0
|
35
|
-
def call(settings)
|
36
|
+
def call(data_set, settings)
|
36
37
|
yaml_data = Qonfig::Loaders::YAML.load_file(file_path, fail_on_unexist: strict)
|
37
38
|
|
38
39
|
raise(
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.13.0
|
5
|
+
class Qonfig::DataSet::Lock
|
6
|
+
# @return [void]
|
7
|
+
#
|
8
|
+
# @api private
|
9
|
+
# @since 0.13.0
|
10
|
+
def initialize
|
11
|
+
@access_lock = Mutex.new
|
12
|
+
@definition_lock = Mutex.new
|
13
|
+
end
|
14
|
+
|
15
|
+
# @param instructions [Proc]
|
16
|
+
# @return [void]
|
17
|
+
#
|
18
|
+
# @api private
|
19
|
+
# @since 0.13.0
|
20
|
+
def thread_safe_access(&instructions)
|
21
|
+
access_lock.owned? ? yield : access_lock.synchronize(&instructions)
|
22
|
+
end
|
23
|
+
|
24
|
+
# @param instructions [Proc]
|
25
|
+
# @return [void]
|
26
|
+
#
|
27
|
+
# @api private
|
28
|
+
# @since 0.13.0
|
29
|
+
def thread_safe_definition(&instructions)
|
30
|
+
definition_lock.owned? ? yield : definition_lock.synchronize(&instructions)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
# @return [Mutex]
|
36
|
+
#
|
37
|
+
# @api private
|
38
|
+
# @since 0.13.0
|
39
|
+
attr_reader :access_lock
|
40
|
+
|
41
|
+
# @return [Mutex]
|
42
|
+
#
|
43
|
+
# @api private
|
44
|
+
# @since 0.13.0
|
45
|
+
attr_reader :definition_lock
|
46
|
+
end
|
data/lib/qonfig/data_set.rb
CHANGED
@@ -2,29 +2,30 @@
|
|
2
2
|
|
3
3
|
# @api public
|
4
4
|
# @since 0.1.0
|
5
|
-
class Qonfig::DataSet
|
5
|
+
class Qonfig::DataSet # rubocop:disable Metrics/ClassLength
|
6
6
|
require_relative 'data_set/class_builder'
|
7
|
-
require_relative 'data_set/
|
7
|
+
require_relative 'data_set/lock'
|
8
8
|
|
9
9
|
# @since 0.1.0
|
10
10
|
extend Qonfig::DSL
|
11
11
|
|
12
|
+
# @since 0.13.0
|
13
|
+
extend Qonfig::Validator::DSL
|
14
|
+
|
12
15
|
# @return [Qonfig::Settings]
|
13
16
|
#
|
14
17
|
# @api private
|
15
18
|
# @since 0.1.0
|
16
19
|
attr_reader :settings
|
17
20
|
|
18
|
-
# @param
|
21
|
+
# @param settings_map [Hash]
|
19
22
|
# @param configurations [Proc]
|
20
23
|
#
|
21
24
|
# @api public
|
22
25
|
# @since 0.1.0
|
23
|
-
def initialize(
|
24
|
-
@
|
25
|
-
|
26
|
-
|
27
|
-
thread_safe_definition { load!(options_map, &configurations) }
|
26
|
+
def initialize(settings_map = {}, &configurations)
|
27
|
+
@__lock__ = Qonfig::DataSet::Lock.new
|
28
|
+
thread_safe_definition { load!(settings_map, &configurations) }
|
28
29
|
end
|
29
30
|
|
30
31
|
# @return [void]
|
@@ -43,7 +44,7 @@ class Qonfig::DataSet
|
|
43
44
|
thread_safe_access { settings.__is_frozen__ }
|
44
45
|
end
|
45
46
|
|
46
|
-
# @param
|
47
|
+
# @param settings_map [Hash]
|
47
48
|
# @param configurations [Proc]
|
48
49
|
# @return [void]
|
49
50
|
#
|
@@ -51,22 +52,21 @@ class Qonfig::DataSet
|
|
51
52
|
#
|
52
53
|
# @api public
|
53
54
|
# @since 0.2.0
|
54
|
-
def reload!(
|
55
|
+
def reload!(settings_map = {}, &configurations)
|
55
56
|
thread_safe_definition do
|
56
57
|
raise Qonfig::FrozenSettingsError, 'Frozen config can not be reloaded' if frozen?
|
57
|
-
load!(
|
58
|
+
load!(settings_map, &configurations)
|
58
59
|
end
|
59
60
|
end
|
60
61
|
|
61
|
-
# @param
|
62
|
+
# @param settings_map [Hash]
|
62
63
|
# @return [void]
|
63
64
|
#
|
64
65
|
# @api public
|
65
66
|
# @since 0.1.0
|
66
|
-
def configure(
|
67
|
+
def configure(settings_map = {}, &configurations)
|
67
68
|
thread_safe_access do
|
68
|
-
|
69
|
-
yield(settings) if block_given?
|
69
|
+
apply_settings(settings_map, &configurations)
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
@@ -172,25 +172,94 @@ class Qonfig::DataSet
|
|
172
172
|
thread_safe_access { settings.__clear__ }
|
173
173
|
end
|
174
174
|
|
175
|
+
# @param block [Proc]
|
176
|
+
# @return [Enumerable]
|
177
|
+
#
|
178
|
+
# @yield [setting_key, setting_value]
|
179
|
+
# @yieldparam setting_key [String]
|
180
|
+
# @yieldparam setting_value [Object]
|
181
|
+
#
|
182
|
+
# @api public
|
183
|
+
# @since 0.13.0
|
184
|
+
def each_setting(&block)
|
185
|
+
thread_safe_access { settings.__each_setting__(&block) }
|
186
|
+
end
|
187
|
+
|
188
|
+
# @param block [Proc]
|
189
|
+
# @return [Enumerable]
|
190
|
+
#
|
191
|
+
# @yield [setting_key, setting_value]
|
192
|
+
# @yieldparam setting_key [String]
|
193
|
+
# @yieldparam setting_value [Object]
|
194
|
+
#
|
195
|
+
# @api public
|
196
|
+
# @since 0.13.0
|
197
|
+
def deep_each_setting(&block)
|
198
|
+
thread_safe_access { settings.__deep_each_setting__(&block) }
|
199
|
+
end
|
200
|
+
|
201
|
+
# @return [Boolean]
|
202
|
+
#
|
203
|
+
# @api public
|
204
|
+
# @since 0.13.0
|
205
|
+
def valid?
|
206
|
+
thread_safe_access { validator.valid? }
|
207
|
+
end
|
208
|
+
|
209
|
+
# @return [void]
|
210
|
+
#
|
211
|
+
# @api public
|
212
|
+
# @since 0.13.0
|
213
|
+
def validate!
|
214
|
+
thread_safe_access { validator.validate! }
|
215
|
+
end
|
216
|
+
|
175
217
|
private
|
176
218
|
|
177
|
-
# @return [Qonfig::
|
219
|
+
# @return [Qonfig::Validator]
|
220
|
+
#
|
221
|
+
# @api private
|
222
|
+
# @since 0.13.0
|
223
|
+
attr_reader :validator
|
224
|
+
|
225
|
+
# @return [void]
|
178
226
|
#
|
179
227
|
# @api private
|
180
228
|
# @since 0.2.0
|
181
229
|
def build_settings
|
182
|
-
Qonfig::Settings::Builder.build(self
|
230
|
+
@settings = Qonfig::Settings::Builder.build(self)
|
231
|
+
validator.validate!
|
232
|
+
end
|
233
|
+
|
234
|
+
# @return [void]
|
235
|
+
#
|
236
|
+
# @api private
|
237
|
+
# @since 0.13.0
|
238
|
+
def build_validator
|
239
|
+
@validator = Qonfig::Validator.new(self)
|
240
|
+
end
|
241
|
+
|
242
|
+
# @param settings_map [Hash]
|
243
|
+
# @param configurations [Proc]
|
244
|
+
# @return [void]
|
245
|
+
#
|
246
|
+
# @api private
|
247
|
+
# @since 0.13.0
|
248
|
+
def apply_settings(settings_map = {}, &configurations)
|
249
|
+
settings.__apply_values__(settings_map)
|
250
|
+
yield(settings) if block_given?
|
183
251
|
end
|
184
252
|
|
185
|
-
# @param
|
253
|
+
# @param settings_map [Hash]
|
186
254
|
# @param configurations [Proc]
|
187
255
|
# @return [void]
|
188
256
|
#
|
189
257
|
# @api private
|
190
258
|
# @since 0.2.0
|
191
|
-
def load!(
|
192
|
-
|
193
|
-
|
259
|
+
def load!(settings_map = {}, &configurations)
|
260
|
+
build_validator
|
261
|
+
build_settings
|
262
|
+
apply_settings(settings_map, &configurations)
|
194
263
|
end
|
195
264
|
|
196
265
|
# @param instructions [Proc]
|
@@ -199,7 +268,7 @@ class Qonfig::DataSet
|
|
199
268
|
# @api private
|
200
269
|
# @since 0.2.0
|
201
270
|
def thread_safe_access(&instructions)
|
202
|
-
@
|
271
|
+
@__lock__.thread_safe_access(&instructions)
|
203
272
|
end
|
204
273
|
|
205
274
|
# @param instructions [Proc]
|
@@ -208,6 +277,6 @@ class Qonfig::DataSet
|
|
208
277
|
# @api private
|
209
278
|
# @since 0.2.0
|
210
279
|
def thread_safe_definition(&instructions)
|
211
|
-
@
|
280
|
+
@__lock__.thread_safe_definition(&instructions)
|
212
281
|
end
|
213
282
|
end
|
data/lib/qonfig/errors.rb
CHANGED
@@ -9,6 +9,14 @@ module Qonfig
|
|
9
9
|
# @since 0.1.0
|
10
10
|
ArgumentError = Class.new(ArgumentError)
|
11
11
|
|
12
|
+
# @api public
|
13
|
+
# @since 0.13.0
|
14
|
+
ValidatorArgumentError = Class.new(ArgumentError)
|
15
|
+
|
16
|
+
# @api public
|
17
|
+
# @since 0.13.0
|
18
|
+
ValidationError = Class.new(Error)
|
19
|
+
|
12
20
|
# @api public
|
13
21
|
# @since 0.12.0
|
14
22
|
PluginError = Class.new(Error)
|
@@ -60,12 +60,13 @@ class Qonfig::Commands::ExposeTOML < Qonfig::Commands::Base
|
|
60
60
|
@env = env
|
61
61
|
end
|
62
62
|
|
63
|
+
# @param data_set [Qonfig::DataSet]
|
63
64
|
# @param settings [Qonfig::Settings]
|
64
65
|
# @return [void]
|
65
66
|
#
|
66
67
|
# @api private
|
67
68
|
# @since 0.12.0
|
68
|
-
def call(settings)
|
69
|
+
def call(data_set, settings)
|
69
70
|
case via
|
70
71
|
when EXPOSERS[:file_name]
|
71
72
|
expose_file_name!(settings)
|
@@ -25,12 +25,13 @@ class Qonfig::Commands::LoadFromTOML < Qonfig::Commands::Base
|
|
25
25
|
@strict = strict
|
26
26
|
end
|
27
27
|
|
28
|
+
# @param data_set [Qonfig::DataSet]
|
28
29
|
# @param settings [Qonfig::Settings]
|
29
30
|
# @return [void]
|
30
31
|
#
|
31
32
|
# @api private
|
32
33
|
# @since 0.12.0
|
33
|
-
def call(settings)
|
34
|
+
def call(data_set, settings)
|
34
35
|
toml_data = Qonfig::Loaders::TOML.load_file(file_path, fail_on_unexist: strict)
|
35
36
|
toml_based_settings = build_data_set_class(toml_data).new.settings
|
36
37
|
settings.__append_settings__(toml_based_settings)
|
@@ -4,14 +4,30 @@
|
|
4
4
|
# @since 0.2.0
|
5
5
|
module Qonfig::Settings::Builder
|
6
6
|
class << self
|
7
|
-
# @param
|
7
|
+
# @param data_set [Qonfig::DataSet]
|
8
8
|
# @return [Qonfig::Settings]
|
9
9
|
#
|
10
10
|
# @api private
|
11
11
|
# @since 0.2.0
|
12
|
-
def build(
|
13
|
-
Qonfig::Settings.new.tap do |settings|
|
14
|
-
commands.each
|
12
|
+
def build(data_set)
|
13
|
+
Qonfig::Settings.new(build_mutation_callbacks(data_set)).tap do |settings|
|
14
|
+
data_set.class.commands.dup.each do |command|
|
15
|
+
command.call(data_set, settings)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
# @param data_set [Qonfig::DataSet]
|
23
|
+
# @return [Qonfig::Settings::Callbacks]
|
24
|
+
#
|
25
|
+
# @api private
|
26
|
+
# @since 0.13.0
|
27
|
+
def build_mutation_callbacks(data_set)
|
28
|
+
Qonfig::Settings::Callbacks.new.tap do |callbacks|
|
29
|
+
# NOTE: validation callbacks
|
30
|
+
callbacks.add(proc { data_set.validate! })
|
15
31
|
end
|
16
32
|
end
|
17
33
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.13.0
|
5
|
+
class Qonfig::Settings::Callbacks
|
6
|
+
# @api private
|
7
|
+
# @since 0.13.0
|
8
|
+
include Enumerable
|
9
|
+
|
10
|
+
# @return [void]
|
11
|
+
#
|
12
|
+
# @api private
|
13
|
+
# @since 0.13.0
|
14
|
+
def initialize
|
15
|
+
@callbacks = []
|
16
|
+
end
|
17
|
+
|
18
|
+
# @return [void]
|
19
|
+
#
|
20
|
+
# @api private
|
21
|
+
# @since 0.13.0
|
22
|
+
def call
|
23
|
+
callbacks.each(&:call)
|
24
|
+
end
|
25
|
+
|
26
|
+
# @param callback [Proc, Qonfig::Settings::Callbacks, #call]
|
27
|
+
# @return [void]
|
28
|
+
#
|
29
|
+
# @api private
|
30
|
+
# @since 0.13.0
|
31
|
+
def add(callback)
|
32
|
+
callbacks << callback
|
33
|
+
end
|
34
|
+
attr_reader :callback
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
# @return [Array<Proc>]
|
39
|
+
#
|
40
|
+
# @api private
|
41
|
+
# @since 0.13.0
|
42
|
+
attr_reader :callbacks
|
43
|
+
end
|