spicerack 0.21.0 → 0.22.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -0
- data/lib/spicerack/configurable.rb +12 -78
- data/lib/spicerack/spec_helper.rb +1 -1
- data/lib/spicerack/version.rb +1 -1
- metadata +31 -29
- data/lib/spicerack/configurable/config_builder.rb +0 -57
- data/lib/spicerack/configurable/config_builder/double_configure.rb +0 -41
- data/lib/spicerack/configurable/config_delegation.rb +0 -47
- data/lib/spicerack/configurable/config_object.rb +0 -63
- data/lib/spicerack/configurable/evaluator.rb +0 -22
- data/lib/spicerack/configurable/reader.rb +0 -46
- data/lib/spicerack/rspec/configurable/dsl.rb +0 -62
- data/lib/spicerack/rspec/configurable/matchers.rb +0 -20
- data/lib/spicerack/rspec/configurable/matchers/configuration/define_config_option.rb +0 -43
- data/lib/spicerack/rspec/configurable/matchers/global/delegate_config_to.rb +0 -64
- data/lib/spicerack/rspec/configurable/spec_helper.rb +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 205c93e2784229099daa8f8fd6a42989a5695a2162dfdb1cf607fa5addfa5374
|
4
|
+
data.tar.gz: d231fde6d44a5bbffbb9e79b521af8b02e2d07decd508e4759086259a2373abf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b06501ebf3fdcfc65ba7073b5e47988ba26f88e7fc28f9df131a2910f9e197245803a1b9b72fffc81509b184d31a71f0f8969ff30340453546269b3d94a411e1
|
7
|
+
data.tar.gz: d7068fede852ab2b25a97e8ef0653ac2cfe4829dad9fbb8810e0a20397ce2bfbcdf268c630c736e6a3e740a066160a3d9dae8b138ef1fb3f6af7c52b828c2624
|
data/README.md
CHANGED
@@ -37,6 +37,7 @@ Or install it yourself as:
|
|
37
37
|
* [AroundTheWorld](around_the_world/README.md) allows you to easily wrap methods with custom logic on any class.
|
38
38
|
* [Collectible](collectible/README.md) provides an extensible framework for building array-like object collections.
|
39
39
|
* [Conjunction](conjunction/README.md) provides a mechanism to loosely coupled a suite of cross-referenced objects.
|
40
|
+
* [Directive](directive/README.md) provides a framework for easily building sane gem configuration classes.
|
40
41
|
* [Facet](facet/README.md) is a filterable, sortable, pageable, and Rails cacheable `ActiveRecord::Relation`.
|
41
42
|
* [RedisHash](redis_hash/README.md) provides a class that matches the Hash api by wrapping Redis.
|
42
43
|
* [RSpice](rspice/README.md) is an `RSpec` utility gem of custom matchers, shared contexts and examples.
|
@@ -1,94 +1,28 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
require_relative "configurable/config_delegation"
|
5
|
-
require_relative "configurable/config_object"
|
6
|
-
require_relative "configurable/evaluator"
|
7
|
-
require_relative "configurable/reader"
|
3
|
+
require "directive"
|
8
4
|
|
9
|
-
# NOTE: This is still a pre-release feature! Use at your own risk - it may change before being released.
|
10
|
-
#
|
11
|
-
# A utility for creating read-only gem configuration singletons.
|
12
|
-
#
|
13
|
-
# Usage:
|
14
|
-
# # In your gem:
|
15
|
-
# module SomeGem
|
16
|
-
# module Configuration
|
17
|
-
# extend Spicerack::Configurable
|
18
|
-
#
|
19
|
-
# configuration_options do
|
20
|
-
# option :some_config_option
|
21
|
-
# option :some_option_with_a_default, default: "I probably know what's best"
|
22
|
-
#
|
23
|
-
# nested :whats_behind do
|
24
|
-
# option :door_one, default: "It's a goat"
|
25
|
-
# option :door_two, default: "Another goat"
|
26
|
-
# option :door_three, default: "It's a car!"
|
27
|
-
# end
|
28
|
-
# end
|
29
|
-
# end
|
30
|
-
# end
|
31
|
-
#
|
32
|
-
# # Then, in the application using the gem:
|
33
|
-
# SomeGem::Configuration.configure do |config|
|
34
|
-
# config.some_config_option = 12345
|
35
|
-
# config.some_option_with_a_default = "Nope, you really don't"
|
36
|
-
#
|
37
|
-
# config.whats_behind do |nested|
|
38
|
-
# nested.door_one = "It's a boat!"
|
39
|
-
# nested.door_three = "The teletubbies on repeat 😱"
|
40
|
-
# end
|
41
|
-
# end
|
42
|
-
#
|
43
|
-
# # Then, back in your gem code:
|
44
|
-
# puts Configuration.config.some_config_option
|
45
|
-
# => 12345
|
46
|
-
# puts Configuration.config.whats_behind.door_one
|
47
|
-
# => "It's a boat!"
|
48
|
-
#
|
49
|
-
# # Or, if you want to select dynamically:
|
50
|
-
# doors = %i[door_one door_two door_three]
|
51
|
-
# Configuration.config.config_eval(whats_behind, doors.sample).read
|
52
|
-
# => "The teletubbies on repeat 😱"
|
53
5
|
module Spicerack
|
6
|
+
# Deprecation support for Directive cutover.
|
54
7
|
module Configurable
|
55
|
-
|
8
|
+
include Directive
|
56
9
|
|
57
|
-
|
58
|
-
|
59
|
-
_config_builder.reader
|
60
|
-
end
|
61
|
-
|
62
|
-
# Run a callback before the configure block is evaluated.
|
63
|
-
#
|
64
|
-
# Note: if configure is called multiple times for your gem, this block will get run each time!
|
65
|
-
#
|
66
|
-
def before_configure(&block)
|
67
|
-
_config_builder_class.set_callback(:configure, :before, &block)
|
68
|
-
end
|
10
|
+
def configuration_options(*args)
|
11
|
+
_display_deprecation_notice
|
69
12
|
|
70
|
-
|
71
|
-
#
|
72
|
-
# Note: if configure is called multiple times for your gem, this block will get run each time!
|
73
|
-
#
|
74
|
-
def after_configure(&block)
|
75
|
-
_config_builder_class.set_callback(:configure, :after, &block)
|
13
|
+
super(*args)
|
76
14
|
end
|
77
15
|
|
78
16
|
private
|
79
17
|
|
80
|
-
def
|
81
|
-
|
82
|
-
end
|
18
|
+
def _display_deprecation_notice
|
19
|
+
return if @deprecation_notice_displayed
|
83
20
|
|
84
|
-
|
85
|
-
@_config_builder ||= _config_builder_class.new
|
86
|
-
end
|
21
|
+
@deprecation_notice_displayed = true
|
87
22
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
end
|
23
|
+
puts "Spicerack::Configurable (used by #{self}) has been deprecated " \
|
24
|
+
"and will be removed in Spicerack #{Gem::Version.new(VERSION).bump}. " \
|
25
|
+
"Please use Directive instead."
|
92
26
|
end
|
93
27
|
end
|
94
28
|
end
|
@@ -4,8 +4,8 @@ require "rspice"
|
|
4
4
|
require "redis_hash/spec_helper"
|
5
5
|
require "technologic/spec_helper"
|
6
6
|
require "tablesalt/spec_helper"
|
7
|
+
require "directive/spec_helper"
|
7
8
|
|
8
9
|
require_relative "rspec/custom_matchers"
|
9
10
|
require_relative "rspec/shared_examples"
|
10
11
|
require_relative "rspec/shoulda_matcher_helper"
|
11
|
-
require_relative "rspec/configurable/spec_helper"
|
data/lib/spicerack/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spicerack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.22.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eric Garside
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2020-01-
|
14
|
+
date: 2020-01-29 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: around_the_world
|
@@ -19,70 +19,84 @@ dependencies:
|
|
19
19
|
requirements:
|
20
20
|
- - '='
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: 0.
|
22
|
+
version: 0.22.0
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
27
|
- - '='
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: 0.
|
29
|
+
version: 0.22.0
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: directive
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
requirements:
|
34
|
+
- - '='
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: 0.22.0
|
37
|
+
type: :runtime
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - '='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.22.0
|
30
44
|
- !ruby/object:Gem::Dependency
|
31
45
|
name: redis_hash
|
32
46
|
requirement: !ruby/object:Gem::Requirement
|
33
47
|
requirements:
|
34
48
|
- - '='
|
35
49
|
- !ruby/object:Gem::Version
|
36
|
-
version: 0.
|
50
|
+
version: 0.22.0
|
37
51
|
type: :runtime
|
38
52
|
prerelease: false
|
39
53
|
version_requirements: !ruby/object:Gem::Requirement
|
40
54
|
requirements:
|
41
55
|
- - '='
|
42
56
|
- !ruby/object:Gem::Version
|
43
|
-
version: 0.
|
57
|
+
version: 0.22.0
|
44
58
|
- !ruby/object:Gem::Dependency
|
45
59
|
name: short_circu_it
|
46
60
|
requirement: !ruby/object:Gem::Requirement
|
47
61
|
requirements:
|
48
62
|
- - '='
|
49
63
|
- !ruby/object:Gem::Version
|
50
|
-
version: 0.
|
64
|
+
version: 0.22.0
|
51
65
|
type: :runtime
|
52
66
|
prerelease: false
|
53
67
|
version_requirements: !ruby/object:Gem::Requirement
|
54
68
|
requirements:
|
55
69
|
- - '='
|
56
70
|
- !ruby/object:Gem::Version
|
57
|
-
version: 0.
|
71
|
+
version: 0.22.0
|
58
72
|
- !ruby/object:Gem::Dependency
|
59
73
|
name: technologic
|
60
74
|
requirement: !ruby/object:Gem::Requirement
|
61
75
|
requirements:
|
62
76
|
- - '='
|
63
77
|
- !ruby/object:Gem::Version
|
64
|
-
version: 0.
|
78
|
+
version: 0.22.0
|
65
79
|
type: :runtime
|
66
80
|
prerelease: false
|
67
81
|
version_requirements: !ruby/object:Gem::Requirement
|
68
82
|
requirements:
|
69
83
|
- - '='
|
70
84
|
- !ruby/object:Gem::Version
|
71
|
-
version: 0.
|
85
|
+
version: 0.22.0
|
72
86
|
- !ruby/object:Gem::Dependency
|
73
87
|
name: tablesalt
|
74
88
|
requirement: !ruby/object:Gem::Requirement
|
75
89
|
requirements:
|
76
90
|
- - '='
|
77
91
|
- !ruby/object:Gem::Version
|
78
|
-
version: 0.
|
92
|
+
version: 0.22.0
|
79
93
|
type: :runtime
|
80
94
|
prerelease: false
|
81
95
|
version_requirements: !ruby/object:Gem::Requirement
|
82
96
|
requirements:
|
83
97
|
- - '='
|
84
98
|
- !ruby/object:Gem::Version
|
85
|
-
version: 0.
|
99
|
+
version: 0.22.0
|
86
100
|
- !ruby/object:Gem::Dependency
|
87
101
|
name: bundler
|
88
102
|
requirement: !ruby/object:Gem::Requirement
|
@@ -207,28 +221,28 @@ dependencies:
|
|
207
221
|
requirements:
|
208
222
|
- - '='
|
209
223
|
- !ruby/object:Gem::Version
|
210
|
-
version: 0.
|
224
|
+
version: 0.22.0
|
211
225
|
type: :development
|
212
226
|
prerelease: false
|
213
227
|
version_requirements: !ruby/object:Gem::Requirement
|
214
228
|
requirements:
|
215
229
|
- - '='
|
216
230
|
- !ruby/object:Gem::Version
|
217
|
-
version: 0.
|
231
|
+
version: 0.22.0
|
218
232
|
- !ruby/object:Gem::Dependency
|
219
233
|
name: spicerack-styleguide
|
220
234
|
requirement: !ruby/object:Gem::Requirement
|
221
235
|
requirements:
|
222
236
|
- - '='
|
223
237
|
- !ruby/object:Gem::Version
|
224
|
-
version: 0.
|
238
|
+
version: 0.22.0
|
225
239
|
type: :development
|
226
240
|
prerelease: false
|
227
241
|
version_requirements: !ruby/object:Gem::Requirement
|
228
242
|
requirements:
|
229
243
|
- - '='
|
230
244
|
- !ruby/object:Gem::Version
|
231
|
-
version: 0.
|
245
|
+
version: 0.22.0
|
232
246
|
- !ruby/object:Gem::Dependency
|
233
247
|
name: will_paginate
|
234
248
|
requirement: !ruby/object:Gem::Requirement
|
@@ -294,12 +308,6 @@ files:
|
|
294
308
|
- lib/spicerack/array_index.rb
|
295
309
|
- lib/spicerack/attribute_object.rb
|
296
310
|
- lib/spicerack/configurable.rb
|
297
|
-
- lib/spicerack/configurable/config_builder.rb
|
298
|
-
- lib/spicerack/configurable/config_builder/double_configure.rb
|
299
|
-
- lib/spicerack/configurable/config_delegation.rb
|
300
|
-
- lib/spicerack/configurable/config_object.rb
|
301
|
-
- lib/spicerack/configurable/evaluator.rb
|
302
|
-
- lib/spicerack/configurable/reader.rb
|
303
311
|
- lib/spicerack/hash_model.rb
|
304
312
|
- lib/spicerack/input_model.rb
|
305
313
|
- lib/spicerack/input_object.rb
|
@@ -312,11 +320,6 @@ files:
|
|
312
320
|
- lib/spicerack/output_object.rb
|
313
321
|
- lib/spicerack/redis_model.rb
|
314
322
|
- lib/spicerack/root_object.rb
|
315
|
-
- lib/spicerack/rspec/configurable/dsl.rb
|
316
|
-
- lib/spicerack/rspec/configurable/matchers.rb
|
317
|
-
- lib/spicerack/rspec/configurable/matchers/configuration/define_config_option.rb
|
318
|
-
- lib/spicerack/rspec/configurable/matchers/global/delegate_config_to.rb
|
319
|
-
- lib/spicerack/rspec/configurable/spec_helper.rb
|
320
323
|
- lib/spicerack/rspec/custom_matchers.rb
|
321
324
|
- lib/spicerack/rspec/custom_matchers/define_argument.rb
|
322
325
|
- lib/spicerack/rspec/custom_matchers/define_attribute.rb
|
@@ -350,8 +353,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
350
353
|
- !ruby/object:Gem::Version
|
351
354
|
version: '0'
|
352
355
|
requirements: []
|
353
|
-
|
354
|
-
rubygems_version: 2.7.6
|
356
|
+
rubygems_version: 3.0.3
|
355
357
|
signing_key:
|
356
358
|
specification_version: 4
|
357
359
|
summary: A suite of utility gems for Ruby on Rails.
|
@@ -1,57 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "technologic"
|
4
|
-
require "active_support/callbacks"
|
5
|
-
|
6
|
-
require_relative "config_builder/double_configure"
|
7
|
-
|
8
|
-
module Spicerack
|
9
|
-
module Configurable
|
10
|
-
class ConfigBuilder
|
11
|
-
include ActiveSupport::Callbacks
|
12
|
-
define_callbacks :configure
|
13
|
-
|
14
|
-
# This concern uses the configure callback, so it needs to be included after the callback is defined
|
15
|
-
include DoubleConfigure
|
16
|
-
|
17
|
-
delegate :config_eval, to: :reader
|
18
|
-
|
19
|
-
def reader
|
20
|
-
@reader ||= Reader.new(configuration)
|
21
|
-
end
|
22
|
-
|
23
|
-
def configure
|
24
|
-
run_callbacks :configure do
|
25
|
-
mutex.synchronize do
|
26
|
-
yield configuration
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
# NOTE: options must be set up before {#configure} is called
|
32
|
-
def option(*args, &block)
|
33
|
-
config_class.__send__(:option, *args, &block)
|
34
|
-
end
|
35
|
-
|
36
|
-
def nested(*args, &block)
|
37
|
-
config_class.__send__(:nested, *args, &block)
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
|
42
|
-
attr_writer :configure_called
|
43
|
-
|
44
|
-
def configuration
|
45
|
-
config_class.instance
|
46
|
-
end
|
47
|
-
|
48
|
-
def config_class
|
49
|
-
@config_class ||= Class.new(ConfigObject)
|
50
|
-
end
|
51
|
-
|
52
|
-
def mutex
|
53
|
-
@mutex = Mutex.new
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "technologic"
|
4
|
-
|
5
|
-
module Spicerack
|
6
|
-
module Configurable
|
7
|
-
module DoubleConfigure
|
8
|
-
extend ActiveSupport::Concern
|
9
|
-
|
10
|
-
include Technologic
|
11
|
-
|
12
|
-
included do
|
13
|
-
set_callback :configure, :after, :warn_on_multiple_configure_calls
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
def configure_called?
|
19
|
-
@configure_called
|
20
|
-
end
|
21
|
-
|
22
|
-
def warn_on_multiple_configure_calls
|
23
|
-
unless configure_called?
|
24
|
-
@configure_called = true
|
25
|
-
return
|
26
|
-
end
|
27
|
-
|
28
|
-
puts <<~WARNING
|
29
|
-
#{self.class._configurable_module_name}.configure has been called more than once, which can lead to unexpected consequences.
|
30
|
-
For the most predictable behavior, configure should only be called once.
|
31
|
-
WARNING
|
32
|
-
end
|
33
|
-
|
34
|
-
module ClassMethods
|
35
|
-
def _configurable_module_name
|
36
|
-
name.gsub("::#{name.demodulize}", "")
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
@@ -1,47 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "active_support/concern"
|
4
|
-
|
5
|
-
module Spicerack
|
6
|
-
module Configurable
|
7
|
-
module ConfigDelegation
|
8
|
-
extend ActiveSupport::Concern
|
9
|
-
|
10
|
-
DEFAULT_CONFIGURATION_MODULE_NAME = "Configuration"
|
11
|
-
|
12
|
-
module ClassMethods
|
13
|
-
delegate :config, :configure, to: :_configuration_module
|
14
|
-
|
15
|
-
private
|
16
|
-
|
17
|
-
# Sets up delegation from a top-level class to a nested Configuration module.
|
18
|
-
#
|
19
|
-
# @example
|
20
|
-
# class SomeClass
|
21
|
-
# include Spicerack::Configurable::ConfigDelegation
|
22
|
-
#
|
23
|
-
# delegates_to_configuration
|
24
|
-
# end
|
25
|
-
#
|
26
|
-
# module SomeClass::Configuration
|
27
|
-
# include Spicerack::Configurable
|
28
|
-
# end
|
29
|
-
#
|
30
|
-
# SomeClass.config
|
31
|
-
# => returns SomeClass::Configuration.config
|
32
|
-
# SomeClass.configure do { |config| # config is the yielded config object from SomeClass::Configuration.configure }
|
33
|
-
#
|
34
|
-
# @param config_class [Spicerack::Configurable] A module that extends Spicerack::Configurable. Defaults to the module +YourGem::Configuration+
|
35
|
-
def delegates_to_configuration(config_class = nil)
|
36
|
-
@_configuration_module = config_class || "#{self}::#{DEFAULT_CONFIGURATION_MODULE_NAME}".constantize
|
37
|
-
end
|
38
|
-
|
39
|
-
def _configuration_module
|
40
|
-
raise NoMethodError, "Configuration not set up for #{self}. Did you forget to call delegates_to_configuration?" if @_configuration_module.nil?
|
41
|
-
|
42
|
-
@_configuration_module
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
@@ -1,63 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Spicerack
|
4
|
-
module Configurable
|
5
|
-
class ConfigObject < InputObject
|
6
|
-
include Singleton
|
7
|
-
include ActiveModel::AttributeAssignment
|
8
|
-
|
9
|
-
alias_method :assign, :assign_attributes
|
10
|
-
|
11
|
-
RESERVED_WORDS = %i[config_eval].freeze
|
12
|
-
|
13
|
-
class_attribute :_nested_options, instance_writer: false, default: []
|
14
|
-
class_attribute :_nested_builders, instance_writer: false, default: {}
|
15
|
-
|
16
|
-
class << self
|
17
|
-
private
|
18
|
-
|
19
|
-
def option(name, *)
|
20
|
-
_ensure_safe_option_name(name)
|
21
|
-
|
22
|
-
super
|
23
|
-
end
|
24
|
-
|
25
|
-
def nested(namespace, &block)
|
26
|
-
_ensure_safe_option_name(namespace)
|
27
|
-
|
28
|
-
nested_config_builder_for(namespace).tap do |builder|
|
29
|
-
builder.instance_exec(&block)
|
30
|
-
|
31
|
-
_nested_options << namespace.to_sym
|
32
|
-
define_method(namespace) do |&nested_configure_block|
|
33
|
-
builder.__send__(:configuration).tap do |nested_config|
|
34
|
-
nested_configure_block.call(nested_config) if nested_configure_block.respond_to?(:call)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def nested_config_builder_for(namespace)
|
41
|
-
_nested_builders[namespace.to_sym] ||= ConfigBuilder.new
|
42
|
-
end
|
43
|
-
|
44
|
-
def _ensure_safe_option_name(name)
|
45
|
-
raise ArgumentError, "#{name.inspect} is reserved and cannot be used at a config option" if name.to_sym.in? RESERVED_WORDS
|
46
|
-
raise ArgumentError, "#{name.inspect} is already in use" if _nested_options.include?(name.to_sym)
|
47
|
-
|
48
|
-
puts "Warning: the config option #{name} is already defined" if _options.include?(name.to_sym) # rubocop:disable Rails/Output
|
49
|
-
end
|
50
|
-
|
51
|
-
def inherited(base)
|
52
|
-
base._nested_options = _nested_options.dup
|
53
|
-
base._nested_builders = _nested_builders.dup
|
54
|
-
super
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def inspect
|
59
|
-
"#<#{self.class.superclass} #{super}>"
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Spicerack
|
4
|
-
module Configurable
|
5
|
-
class Evaluator
|
6
|
-
# @param path [Array<Symbol, String>] A message path for the desired config
|
7
|
-
# @param configuration [Spicerack::Configurable::Reader]
|
8
|
-
def initialize(path, configuration)
|
9
|
-
@path = path
|
10
|
-
@configuration = configuration
|
11
|
-
end
|
12
|
-
|
13
|
-
def read
|
14
|
-
path.inject(configuration, &:public_send)
|
15
|
-
end
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
attr_reader :path, :configuration
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,46 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Spicerack
|
4
|
-
module Configurable
|
5
|
-
class Reader
|
6
|
-
include Tablesalt::StringableObject
|
7
|
-
|
8
|
-
def initialize(config)
|
9
|
-
@config = config
|
10
|
-
end
|
11
|
-
|
12
|
-
def config_eval(*path)
|
13
|
-
Evaluator.new(path, self)
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
attr_reader :config
|
19
|
-
|
20
|
-
def method_missing(method_name, *)
|
21
|
-
name = method_name.to_sym
|
22
|
-
|
23
|
-
return mutex.synchronize { config.public_send(name) } if config._options.map(&:to_sym).include?(name)
|
24
|
-
return config._nested_builders[name].reader if config._nested_builders.key?(name)
|
25
|
-
|
26
|
-
super
|
27
|
-
end
|
28
|
-
|
29
|
-
def respond_to_missing?(method_name, *)
|
30
|
-
name = method_name.to_sym
|
31
|
-
|
32
|
-
config._options.map(&:to_sym).include?(name) ||
|
33
|
-
config._nested_builders.key?(name) ||
|
34
|
-
super
|
35
|
-
end
|
36
|
-
|
37
|
-
def mutex
|
38
|
-
@mutex ||= Mutex.new
|
39
|
-
end
|
40
|
-
|
41
|
-
def stringable_attributes
|
42
|
-
config._options + config._nested_options
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
@@ -1,62 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "matchers"
|
4
|
-
|
5
|
-
module Spicerack
|
6
|
-
module RSpec
|
7
|
-
module Configurable
|
8
|
-
module DSL
|
9
|
-
def nested_config_option(config_name, &block)
|
10
|
-
in_nested_config_stack(config_name) do |nested_stack|
|
11
|
-
describe(config_name.to_s, caller: caller) do
|
12
|
-
subject { nested_config }
|
13
|
-
|
14
|
-
let(:parent_config) { parent_config_for_nested(nested_stack) }
|
15
|
-
let(:nested_config) { parent_config.public_send(nested_stack.last) }
|
16
|
-
|
17
|
-
it "defines nested config object #{config_name}" do
|
18
|
-
expect(parent_config).to respond_to config_name
|
19
|
-
expect(parent_config._nested_options).to include config_name.to_sym
|
20
|
-
expect(parent_config.public_send(config_name)).to be_a Spicerack::Configurable::ConfigObject
|
21
|
-
end
|
22
|
-
|
23
|
-
instance_eval(&block)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def self.included(base)
|
29
|
-
base.extend DSL
|
30
|
-
super
|
31
|
-
end
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
def parent_config_for_nested(nested_stack)
|
36
|
-
@parent_config ||= {}
|
37
|
-
|
38
|
-
@parent_config[nested_stack] ||= described_class.
|
39
|
-
__send__(:_config_builder).
|
40
|
-
__send__(:configuration).
|
41
|
-
yield_self do |config|
|
42
|
-
nested_stack[0..-2].inject(config) do |conf, nested_name|
|
43
|
-
conf.public_send(nested_name)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def in_nested_config_stack(name)
|
49
|
-
_nested_config_stack << name.to_sym
|
50
|
-
|
51
|
-
yield _nested_config_stack.dup
|
52
|
-
|
53
|
-
_nested_config_stack.pop
|
54
|
-
end
|
55
|
-
|
56
|
-
def _nested_config_stack
|
57
|
-
Thread.current[:nested_config_stack] ||= []
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Spicerack
|
4
|
-
module RSpec
|
5
|
-
module Configurable
|
6
|
-
module Matchers
|
7
|
-
module Configuration
|
8
|
-
extend ::RSpec::Matchers::DSL
|
9
|
-
end
|
10
|
-
|
11
|
-
module Global
|
12
|
-
extend ::RSpec::Matchers::DSL
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
require_relative "matchers/configuration/define_config_option"
|
20
|
-
require_relative "matchers/global/delegate_config_to"
|
@@ -1,43 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Spicerack
|
4
|
-
module RSpec
|
5
|
-
module Configurable
|
6
|
-
module Matchers
|
7
|
-
module Configuration
|
8
|
-
# RSpec matcher to test options of a Configurable class
|
9
|
-
#
|
10
|
-
# class ExampleConfiguration
|
11
|
-
# include Spicerack::Configurable
|
12
|
-
#
|
13
|
-
# option :foo
|
14
|
-
# option :bar, default: :baz
|
15
|
-
# end
|
16
|
-
#
|
17
|
-
# RSpec.describe ExampleConfiguration, type: :configuration do
|
18
|
-
# subject { described_class.new }
|
19
|
-
#
|
20
|
-
# it { is_expected.to define_config_option :foo }
|
21
|
-
# it { is_expected.to define_config_option :bar, default: :baz }
|
22
|
-
# end
|
23
|
-
define :define_config_option do |option, default: nil|
|
24
|
-
description { "define config option #{option.inspect}" }
|
25
|
-
failure_message { "expected #{@obj} to define config option #{option.inspect} with default #{default.inspect}" }
|
26
|
-
|
27
|
-
match do |obj|
|
28
|
-
@obj = obj
|
29
|
-
|
30
|
-
if obj.is_a? Spicerack::Configurable::ConfigObject
|
31
|
-
expect(obj).to define_option option, default: default
|
32
|
-
else
|
33
|
-
expect(obj).to respond_to :config
|
34
|
-
expect(obj.config.instance_variable_get(:@config)).to be_present
|
35
|
-
expect(obj.config.instance_variable_get(:@config)).to define_option option, default: default
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
@@ -1,64 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Spicerack
|
4
|
-
module RSpec
|
5
|
-
module Configurable
|
6
|
-
module Matchers
|
7
|
-
module Global
|
8
|
-
# RSpec matcher to test options of a Configurable class
|
9
|
-
#
|
10
|
-
# module MyGem
|
11
|
-
# include Spicerack::Configurable::ConfigDelegation
|
12
|
-
# delegates_to_configuration
|
13
|
-
#
|
14
|
-
# class MyGem::Configuration
|
15
|
-
# include Spicerack::Configurable
|
16
|
-
# ...
|
17
|
-
# end
|
18
|
-
# end
|
19
|
-
#
|
20
|
-
# RSpec.describe ExampleConfiguration, type: :configuration do
|
21
|
-
# subject { described_class }
|
22
|
-
#
|
23
|
-
# it { is_expected.to delegate_config_to MyGem::Configuration }
|
24
|
-
# end
|
25
|
-
define :delegate_config_to do |config_module|
|
26
|
-
attr_reader :obj, :config_module
|
27
|
-
|
28
|
-
description { "delegates configuration methods to #{config_module}" }
|
29
|
-
|
30
|
-
failure_message { "expected #{target} to delegate configuration methods to #{config_module}" }
|
31
|
-
failure_message_when_negated { "expected #{target} not to delegate configuration methods to #{config_module}" }
|
32
|
-
|
33
|
-
match_unless_raises do |obj|
|
34
|
-
@obj = obj
|
35
|
-
@config_module = config_module
|
36
|
-
|
37
|
-
stub_configuration_methods
|
38
|
-
|
39
|
-
expect(target.config).to eq config_return_value
|
40
|
-
expect(target.configure).to eq configure_return_value
|
41
|
-
end
|
42
|
-
|
43
|
-
def target
|
44
|
-
obj.is_a?(Module) ? obj : obj.class
|
45
|
-
end
|
46
|
-
|
47
|
-
def stub_configuration_methods
|
48
|
-
allow(config_module).to receive(:config).and_return(config_return_value)
|
49
|
-
allow(config_module).to receive(:configure).and_return(configure_return_value)
|
50
|
-
end
|
51
|
-
|
52
|
-
def config_return_value
|
53
|
-
@config_return_value ||= double
|
54
|
-
end
|
55
|
-
|
56
|
-
def configure_return_value
|
57
|
-
@configure_return_value ||= double
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
@@ -1,10 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "matchers"
|
4
|
-
require_relative "dsl"
|
5
|
-
|
6
|
-
RSpec.configure do |config|
|
7
|
-
config.include(Spicerack::RSpec::Configurable::Matchers::Global)
|
8
|
-
config.include(Spicerack::RSpec::Configurable::Matchers::Configuration, type: :configuration)
|
9
|
-
config.include(Spicerack::RSpec::Configurable::DSL, type: :configuration)
|
10
|
-
end
|