spicerack 0.21.0 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/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
|