configurations 1.1.0 → 1.3.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.
- data/.gitignore +1 -0
- data/.ruby-version +1 -1
- data/README.md +70 -3
- data/lib/configurations.rb +1 -1
- data/lib/configurations/configurable.rb +29 -4
- data/lib/configurations/configuration.rb +46 -17
- data/test/configurations/test_configurable_with_blocks_configuration.rb +46 -0
- data/test/configurations/test_configuration_methods.rb +67 -0
- metadata +18 -6
- checksums.yaml +0 -7
data/.gitignore
CHANGED
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
1.9.3-p547
|
data/README.md
CHANGED
@@ -112,13 +112,81 @@ MyGem.configure do |c|
|
|
112
112
|
end
|
113
113
|
```
|
114
114
|
|
115
|
+
### Fourth way: Custom asserted or changed values
|
116
|
+
|
117
|
+
If you need further assertions or you need to change a value before it gets stored in the configuration, consider passing a block
|
118
|
+
|
119
|
+
```
|
120
|
+
module MyGem
|
121
|
+
include Configurations
|
122
|
+
configurable :foo do |value|
|
123
|
+
|
124
|
+
# The return value is what gets assigned, unless it is nil,
|
125
|
+
# in which case the original value persists
|
126
|
+
#
|
127
|
+
value + ' ooooh my'
|
128
|
+
end
|
129
|
+
configurable String, bar: :baz do |value|
|
130
|
+
|
131
|
+
# value is guaranteed to be a string at this point
|
132
|
+
#
|
133
|
+
unless %w(bi ba bu).include?(value)
|
134
|
+
raise ArgumentError, 'baz needs to be one of bi, ba, bu'
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
```
|
139
|
+
|
140
|
+
Gives your users:
|
141
|
+
|
142
|
+
```
|
143
|
+
MyGem.configure do |c|
|
144
|
+
c.foo = 'FOO'
|
145
|
+
c.bar.baz = %w(bi)
|
146
|
+
|
147
|
+
# This would raise the ArgumentError in the block
|
148
|
+
# c.bar.baz = %w(boooh)
|
149
|
+
end
|
150
|
+
```
|
151
|
+
|
115
152
|
Gives you:
|
116
153
|
|
117
154
|
```
|
118
|
-
MyGem.configuration.foo #=>
|
119
|
-
MyGem.configuration.bar.baz #=>
|
155
|
+
MyGem.configuration.foo #=> 'FOO ooooh my'
|
156
|
+
MyGem.configuration.bar.baz #=> one of %w(bi ba bu)
|
120
157
|
```
|
121
158
|
|
159
|
+
### Configuration Methods
|
160
|
+
|
161
|
+
You might want to define methods on your configuration which use configuration values to bring out another value.
|
162
|
+
This is what `configuration_method` is here to help you with:
|
163
|
+
|
164
|
+
```
|
165
|
+
module MyGem
|
166
|
+
include Configurations
|
167
|
+
configurable :foo, :bar
|
168
|
+
configuration_method :foobar do |arg|
|
169
|
+
foo + bar + arg
|
170
|
+
end
|
171
|
+
end
|
172
|
+
```
|
173
|
+
|
174
|
+
Your users do:
|
175
|
+
|
176
|
+
```
|
177
|
+
MyGem.configure do |c|
|
178
|
+
c.foo = 'FOO'
|
179
|
+
c.bar = 'BAR'
|
180
|
+
end
|
181
|
+
```
|
182
|
+
|
183
|
+
You get:
|
184
|
+
|
185
|
+
```
|
186
|
+
MyGem.configuration.foobar('ARG') #=> 'FOOBARARG'
|
187
|
+
```
|
188
|
+
|
189
|
+
|
122
190
|
### Defaults:
|
123
191
|
|
124
192
|
```
|
@@ -134,7 +202,6 @@ end
|
|
134
202
|
|
135
203
|
```
|
136
204
|
MyGem.configuration.to_h #=> a Hash
|
137
|
-
|
138
205
|
```
|
139
206
|
|
140
207
|
### Some caveats
|
data/lib/configurations.rb
CHANGED
@@ -49,11 +49,31 @@ module Configurations
|
|
49
49
|
# configurable can be used to set the properties which should be configurable, as well as a type which
|
50
50
|
# the given property should be asserted to
|
51
51
|
# @param [Class, Symbol, Hash] properties a type as a first argument to type assert (if any) or nested properties to allow for setting
|
52
|
+
# @param [Proc] block a block with arity 2 to evaluate when a property is set. It will be given: property name and value
|
52
53
|
#
|
53
|
-
def configurable(*properties)
|
54
|
+
def configurable(*properties, &block)
|
54
55
|
type = properties.shift if properties.first.is_a?(Class)
|
55
56
|
@configurable ||= {}
|
56
|
-
@configurable.merge!(to_configurable_hash(properties, type))
|
57
|
+
@configurable.merge!(to_configurable_hash(properties, type, &block))
|
58
|
+
end
|
59
|
+
|
60
|
+
# returns whether a property is set to be configurable
|
61
|
+
# @param [Symbol] property the property to ask status for
|
62
|
+
#
|
63
|
+
def configurable?(property)
|
64
|
+
@configurable.is_a?(Hash) && @configurable.has_key?(property)
|
65
|
+
end
|
66
|
+
|
67
|
+
# configuration method can be used to retrieve properties from the configuration which use your gem's context
|
68
|
+
# @param [Class, Symbol, Hash] properties properties for retrieval
|
69
|
+
# @param [Proc] block the block to evaluate
|
70
|
+
#
|
71
|
+
def configuration_method(method, &block)
|
72
|
+
raise ArgumentError, "#{method} can not be both a configurable property and a configuration method" if configurable?(method)
|
73
|
+
|
74
|
+
Configuration.class_eval do
|
75
|
+
define_method method, &block
|
76
|
+
end
|
57
77
|
end
|
58
78
|
|
59
79
|
private
|
@@ -63,8 +83,13 @@ module Configurations
|
|
63
83
|
# @param [Class] type the type to assert, if any
|
64
84
|
# @return a hash with configurable values pointing to their types
|
65
85
|
#
|
66
|
-
def to_configurable_hash(properties, type)
|
67
|
-
|
86
|
+
def to_configurable_hash(properties, type, &block)
|
87
|
+
assertion_hash = {}
|
88
|
+
assertion_hash.merge! block: block if block_given?
|
89
|
+
assertion_hash.merge! type: type if type
|
90
|
+
|
91
|
+
assertions = ([assertion_hash] * properties.size)
|
92
|
+
Hash[properties.zip(assertions)]
|
68
93
|
end
|
69
94
|
end
|
70
95
|
end
|
@@ -59,21 +59,21 @@ module Configurations
|
|
59
59
|
#
|
60
60
|
def method_missing(method, *args, &block)
|
61
61
|
property = method.to_s[0..-2].to_sym
|
62
|
+
value = args.first
|
62
63
|
|
63
64
|
if _is_writer?(method) && @_writeable && _configurable?(property)
|
64
|
-
|
65
|
-
@configuration[property] = args.first
|
65
|
+
_assign!(property, value)
|
66
66
|
elsif !_is_writer?(method) && @_writeable || _configured?(method)
|
67
67
|
@configuration[method]
|
68
68
|
else
|
69
|
-
|
69
|
+
::Kernel.send(method, *args, &block)
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
73
|
# Respond to missing according to the method_missing implementation
|
74
74
|
#
|
75
75
|
def respond_to_missing?(method, include_private = false)
|
76
|
-
is_setter?(method) || @_writeable || _configured?(method) ||
|
76
|
+
is_setter?(method) || @_writeable || _configured?(method) || ::Kernel.respond_to_missing?(method, include_private)
|
77
77
|
end
|
78
78
|
|
79
79
|
# Set the configuration to writeable or read only. Access to writer methods is only allowed within the
|
@@ -98,8 +98,6 @@ module Configurations
|
|
98
98
|
end
|
99
99
|
end
|
100
100
|
|
101
|
-
private
|
102
|
-
|
103
101
|
# @param [Symbol] property The property to test for configurability
|
104
102
|
# @return [Boolean] whether the given property is configurable
|
105
103
|
#
|
@@ -107,6 +105,15 @@ module Configurations
|
|
107
105
|
_arbitrarily_configurable? or @configurable.has_key?(property)
|
108
106
|
end
|
109
107
|
|
108
|
+
|
109
|
+
# @return [Boolean] whether this configuration is arbitrarily configurable
|
110
|
+
#
|
111
|
+
def _arbitrarily_configurable?
|
112
|
+
@configurable.nil? or @configurable.empty?
|
113
|
+
end
|
114
|
+
|
115
|
+
private
|
116
|
+
|
110
117
|
# @param [Symbol] property The property to test for
|
111
118
|
# @return [Boolean] whether the given property has been configured
|
112
119
|
#
|
@@ -127,10 +134,10 @@ module Configurations
|
|
127
134
|
def _evaluate_configurable!
|
128
135
|
return if _arbitrarily_configurable?
|
129
136
|
|
130
|
-
@configurable.each do |k,
|
137
|
+
@configurable.each do |k, assertion|
|
131
138
|
if k.is_a?(::Hash)
|
132
139
|
k.each do |property, nested|
|
133
|
-
@configuration[property] = Configuration.new(nil, _to_configurable_hash(nested,
|
140
|
+
@configuration[property] = Configuration.new(nil, _to_configurable_hash(nested, assertion))
|
134
141
|
end
|
135
142
|
end
|
136
143
|
end
|
@@ -140,9 +147,20 @@ module Configurations
|
|
140
147
|
# @param [Class] type the type to assert, if any
|
141
148
|
# @return a hash with configurable values pointing to their types
|
142
149
|
#
|
143
|
-
def _to_configurable_hash(value,
|
150
|
+
def _to_configurable_hash(value, assertion)
|
144
151
|
value = [value] unless value.is_a?(::Array)
|
145
|
-
::Hash[value.zip([
|
152
|
+
::Hash[value.zip([assertion].flatten*value.size)]
|
153
|
+
end
|
154
|
+
|
155
|
+
# Assigns a value after running the assertions
|
156
|
+
# @param [Symbol] property the property to type test
|
157
|
+
# @param [Any] value the given value
|
158
|
+
#
|
159
|
+
def _assign!(property, value)
|
160
|
+
v = _evaluate_block!(property, value)
|
161
|
+
value = v unless v.nil?
|
162
|
+
_assert_type!(property, value)
|
163
|
+
@configuration[property] = value
|
146
164
|
end
|
147
165
|
|
148
166
|
# Type assertion for configurable properties
|
@@ -151,18 +169,29 @@ module Configurations
|
|
151
169
|
# @raise [ConfigurationError] if the given value has the wrong type
|
152
170
|
#
|
153
171
|
def _assert_type!(property, value)
|
154
|
-
return
|
172
|
+
return unless _evaluable?(property, :type)
|
155
173
|
|
156
|
-
|
157
|
-
|
174
|
+
assertion = @configurable[property][:type]
|
175
|
+
::Kernel.raise ConfigurationError, "Expected #{property} to be configured with #{expected_type}, but got #{value.class.inspect}", caller unless value.is_a?(assertion)
|
176
|
+
end
|
158
177
|
|
159
|
-
|
178
|
+
# Block assertion for configurable properties
|
179
|
+
# @param [Symbol] property the property to type test
|
180
|
+
# @param [Any] value the given value
|
181
|
+
#
|
182
|
+
def _evaluate_block!(property, value)
|
183
|
+
return value unless _evaluable?(property, :block)
|
184
|
+
|
185
|
+
evaluation = @configurable[property][:block]
|
186
|
+
evaluation.call(value)
|
160
187
|
end
|
161
188
|
|
162
|
-
# @
|
189
|
+
# @param [Symbol] property The property to test for
|
190
|
+
# @param [Symbol] assertion_type The evaluation type type to test for
|
191
|
+
# @return [Boolean] whether the given property is assertable
|
163
192
|
#
|
164
|
-
def
|
165
|
-
@configurable.
|
193
|
+
def _evaluable?(property, evaluation)
|
194
|
+
@configurable and @configurable.has_key?(property) and @configurable[property].is_a?(::Hash) and @configurable[property].has_key?(evaluation)
|
166
195
|
end
|
167
196
|
|
168
197
|
# @param [Symbol] method the method to test for
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TestStricterConfigurationWithBlock < Minitest::Test
|
4
|
+
|
5
|
+
BlocksConfigurationTestModule = testmodule_for(Configurations)
|
6
|
+
BlocksConfigurationTestModule.module_eval do
|
7
|
+
configurable :property1, :property2 do |value|
|
8
|
+
value.to_s + 'oooh'
|
9
|
+
end
|
10
|
+
configurable String, :property3, property4: [:property5, :property6] do |value|
|
11
|
+
raise ArgumentError, 'TEST2' unless %w(hello bye).include?(value)
|
12
|
+
value
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def setup
|
17
|
+
BlocksConfigurationTestModule.configure do |c|
|
18
|
+
c.property1 = :one
|
19
|
+
c.property2 = :two
|
20
|
+
c.property3 = 'hello'
|
21
|
+
c.property4.property5 = 'hello'
|
22
|
+
c.property4.property6 = 'bye'
|
23
|
+
end
|
24
|
+
|
25
|
+
@configuration = BlocksConfigurationTestModule.configuration
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_configurable_when_set_configurable_with_block
|
29
|
+
assert_equal 'oneoooh', @configuration.property1
|
30
|
+
assert_equal 'twooooh', @configuration.property2
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_nested_configurable_when_set_configurable_with_block
|
34
|
+
assert_equal 'hello', @configuration.property4.property5
|
35
|
+
assert_equal 'bye', @configuration.property4.property6
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_evaluates_block_for_nested_properties_when_set_configurable_with_block
|
39
|
+
assert_raises ArgumentError, 'TEST2' do
|
40
|
+
BlocksConfigurationTestModule.configure do |c|
|
41
|
+
c.property4.property5 = 'oh'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TestConfigurationMethods < Minitest::Test
|
4
|
+
|
5
|
+
ConfigurationMethodsClassModule = testmodule_for(Configurations)
|
6
|
+
ConfigurationMethodsClassModule.module_eval do
|
7
|
+
class MyClass
|
8
|
+
attr_reader :props
|
9
|
+
def initialize(*props)
|
10
|
+
@props = props
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context = 'CONTEXT'
|
15
|
+
configurable :property1, :property2
|
16
|
+
configuration_method :method1 do
|
17
|
+
MyClass.new(property1, property2)
|
18
|
+
end
|
19
|
+
configuration_method :method2 do
|
20
|
+
context + property1.to_s
|
21
|
+
end
|
22
|
+
configuration_method :method3 do |arg|
|
23
|
+
arg + property1.to_s
|
24
|
+
end
|
25
|
+
configuration_method :kernel_raise do
|
26
|
+
raise StandardError, 'hell'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def setup
|
31
|
+
ConfigurationMethodsClassModule.configure do |c|
|
32
|
+
c.property1 = :one
|
33
|
+
c.property2 = :two
|
34
|
+
end
|
35
|
+
|
36
|
+
@configuration = ConfigurationMethodsClassModule.configuration
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_configuration_method
|
40
|
+
assert_equal [:one, :two], @configuration.method1.props
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_configuration_method_with_context
|
44
|
+
assert_equal 'CONTEXTone', @configuration.method2
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_configuration_method_with_arguments
|
48
|
+
assert_equal 'ARGone', @configuration.method3('ARG')
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_kernel_methods_in_configuration_method
|
52
|
+
assert_raises StandardError, 'hell' do
|
53
|
+
@configuration.kernel_raise
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_configuration_method_overwrite
|
58
|
+
assert_raises ArgumentError do
|
59
|
+
ConfigurationMethodsClassModule.module_eval do
|
60
|
+
configuration_method :property2 do |c|
|
61
|
+
MyClass.new(c.property2)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: configurations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- Beat Richartz
|
@@ -13,6 +14,7 @@ dependencies:
|
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: minitest
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
16
18
|
requirements:
|
17
19
|
- - ~>
|
18
20
|
- !ruby/object:Gem::Version
|
@@ -20,6 +22,7 @@ dependencies:
|
|
20
22
|
type: :development
|
21
23
|
prerelease: false
|
22
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
23
26
|
requirements:
|
24
27
|
- - ~>
|
25
28
|
- !ruby/object:Gem::Version
|
@@ -27,6 +30,7 @@ dependencies:
|
|
27
30
|
- !ruby/object:Gem::Dependency
|
28
31
|
name: yard
|
29
32
|
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
30
34
|
requirements:
|
31
35
|
- - ~>
|
32
36
|
- !ruby/object:Gem::Version
|
@@ -34,6 +38,7 @@ dependencies:
|
|
34
38
|
type: :development
|
35
39
|
prerelease: false
|
36
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
37
42
|
requirements:
|
38
43
|
- - ~>
|
39
44
|
- !ruby/object:Gem::Version
|
@@ -41,6 +46,7 @@ dependencies:
|
|
41
46
|
- !ruby/object:Gem::Dependency
|
42
47
|
name: rake
|
43
48
|
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
44
50
|
requirements:
|
45
51
|
- - ~>
|
46
52
|
- !ruby/object:Gem::Version
|
@@ -48,6 +54,7 @@ dependencies:
|
|
48
54
|
type: :development
|
49
55
|
prerelease: false
|
50
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
51
58
|
requirements:
|
52
59
|
- - ~>
|
53
60
|
- !ruby/object:Gem::Version
|
@@ -72,37 +79,42 @@ files:
|
|
72
79
|
- lib/configurations/configurable.rb
|
73
80
|
- lib/configurations/configuration.rb
|
74
81
|
- lib/configurations/error.rb
|
82
|
+
- test/configurations/test_configurable_with_blocks_configuration.rb
|
75
83
|
- test/configurations/test_configuration.rb
|
84
|
+
- test/configurations/test_configuration_methods.rb
|
76
85
|
- test/configurations/test_stricter_configuration.rb
|
77
86
|
- test/support/testmodules.rb
|
78
87
|
- test/test_helper.rb
|
79
88
|
homepage: http://github.com/beatrichartz/configurations
|
80
89
|
licenses:
|
81
90
|
- MIT
|
82
|
-
metadata: {}
|
83
91
|
post_install_message:
|
84
92
|
rdoc_options: []
|
85
93
|
require_paths:
|
86
94
|
- lib
|
87
95
|
required_ruby_version: !ruby/object:Gem::Requirement
|
96
|
+
none: false
|
88
97
|
requirements:
|
89
|
-
- - '>='
|
98
|
+
- - ! '>='
|
90
99
|
- !ruby/object:Gem::Version
|
91
100
|
version: '0'
|
92
101
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
|
+
none: false
|
93
103
|
requirements:
|
94
|
-
- - '>='
|
104
|
+
- - ! '>='
|
95
105
|
- !ruby/object:Gem::Version
|
96
106
|
version: '0'
|
97
107
|
requirements: []
|
98
108
|
rubyforge_project:
|
99
|
-
rubygems_version:
|
109
|
+
rubygems_version: 1.8.23.2
|
100
110
|
signing_key:
|
101
|
-
specification_version:
|
111
|
+
specification_version: 3
|
102
112
|
summary: Configurations with a configure block from arbitrary to type-restricted for
|
103
113
|
your gem or other ruby code.
|
104
114
|
test_files:
|
115
|
+
- test/configurations/test_configurable_with_blocks_configuration.rb
|
105
116
|
- test/configurations/test_configuration.rb
|
117
|
+
- test/configurations/test_configuration_methods.rb
|
106
118
|
- test/configurations/test_stricter_configuration.rb
|
107
119
|
- test/support/testmodules.rb
|
108
120
|
- test/test_helper.rb
|
checksums.yaml
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz: 039597b55adc73ff8cddc05edd7c199f5f2c252f
|
4
|
-
data.tar.gz: 1dec69ab7582283ab60f950dc3caa96e92ff2b95
|
5
|
-
SHA512:
|
6
|
-
metadata.gz: e7a927942a4bce9f187a1f491f9469ac898cc62e2687c3b2111163d6b8b665ebaea70767f52fabcdb2e11c1544bc005168610317632ecabe8211373c993897d3
|
7
|
-
data.tar.gz: 97ae55c4e7c2ccae76aab97aa75c912c4b79bbf4a5fc7ebdb752b7150d9b0be821598fc9f060f484e7b456a1a153072a5a5672260c2ca96548d1c2789c6ca89e
|