sinclair 1.3.1 → 1.3.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c574eec3a6df9fca413808866c33a03da39ac3aea5a55ad588ea0532fdcb8058
4
- data.tar.gz: ccdf5e26711abfeb0c9a2eee9f59cabc8a4ae912b624b976720b228b7be7adbd
3
+ metadata.gz: 5a99344876ea7ff46dc785f5d9a9daddedce4fa84fb1d33c1387f333ef2611f8
4
+ data.tar.gz: 2687f7ebd7816a13275d9aede938dff46731edde1dba1b2e0a272f9e0967af18
5
5
  SHA512:
6
- metadata.gz: 807968f16b1be5c991e7377aa888fc70548c8058945e7f137a6cfa53ef4a6359c5be19305a5184f8d2b1d7ed8343d815a8595b9deef8b1f266c7e5fbca4bc94f
7
- data.tar.gz: 2dc1e2cbf9e95829d488e49ee6835775d99cc9743313b0b58ea50fc2ac739a471ecd98da35c9193dc631bcbfdfabe6cb665fa190a97afacf4b4d4ecfec9dde95
6
+ metadata.gz: 8b6278abe2c8f3b0ec4f20cc9856508cf7f5726643229d532c075e5a142cca02141f5e3e8b8d99bea25859dd2a4b072b2fb457aa0b682f4a25949f132c2715e4
7
+ data.tar.gz: d0e6cae7c4e3d1f87c99f737066292cdee42ee6b14c00ce7b1a6cb1eb20f05dd73a776e5cd75c3ac2d6ffb7ab1a91a67f57d5d0d00385238aa57ab84dbc6d7bb
data/README.md CHANGED
@@ -14,7 +14,7 @@ methods
14
14
 
15
15
  Yard Documentation
16
16
  -------------------
17
- https://www.rubydoc.info/gems/sinclair/1.3.1
17
+ https://www.rubydoc.info/gems/sinclair/1.3.2
18
18
 
19
19
  Installation
20
20
  ---------------
@@ -314,7 +314,8 @@ the `configurable#configure` method
314
314
  class MyConfigurable
315
315
  extend Sinclair::Configurable
316
316
 
317
- configurable_with :host, :port
317
+ # port is defaulted to 80
318
+ configurable_with :host, port: 80
318
319
  end
319
320
 
320
321
  MyConfigurable.configure do |config|
@@ -328,7 +329,7 @@ the `configurable#configure` method
328
329
  MyConfigurable.reset_config
329
330
 
330
331
  MyConfigurable.config.host # returns nil
331
- MyConfigurable.config.port # returns nil
332
+ MyConfigurable.config.port # returns 80
332
333
  ```
333
334
 
334
335
  RSspec matcher
data/config/yardstick.yml CHANGED
@@ -18,6 +18,9 @@ rules:
18
18
  exclude:
19
19
  - Sinclair::OptionsParser#options
20
20
  - Sinclair::OptionsParser#options_object
21
+ - Sinclair::Configurable#config
22
+ - Sinclair::Configurable#reset_config
23
+ - Sinclair::Configurable#configure
21
24
  ReturnTag:
22
25
  enabled: true
23
26
  exclude:
@@ -34,6 +37,11 @@ rules:
34
37
  - Sinclair::ConfigFactory#initialize
35
38
  - Sinclair::ConfigFactory#config_class
36
39
  - Sinclair::ConfigFactory#config_attributes
40
+ - Sinclair::ConfigFactory::MethodsBuilder#names
41
+ - Sinclair::ConfigFactory::MethodsBuilder#defaults
42
+ - Sinclair::Configurable#config
43
+ - Sinclair::Configurable#reset_config
44
+ - Sinclair::Configurable#configure
37
45
  Summary::Presence:
38
46
  enabled: true
39
47
  exclude:
@@ -52,6 +60,9 @@ rules:
52
60
  - Sinclair::ConfigFactory#initialize
53
61
  - Sinclair::ConfigFactory#config_class
54
62
  - Sinclair::ConfigFactory#config_attributes
63
+ - Sinclair::ConfigFactory::MethodsBuilder#initialize
64
+ - Sinclair::ConfigFactory::MethodsBuilder#names
65
+ - Sinclair::ConfigFactory::MethodsBuilder#defaults
55
66
  Summary::Length:
56
67
  enabled: true
57
68
  exclude: []
@@ -16,6 +16,8 @@ class Sinclair
16
16
  # factory.config.equal?(config) # returns true
17
17
  # config.name # returns 'John'
18
18
  class ConfigFactory
19
+ autoload :MethodsBuilder, 'sinclair/config_factory/methods_builder'
20
+
19
21
  # @param config_class [Class] configuration class to be used
20
22
  # @param config_attributes [Array<Symbol,String>] list of possible configurations
21
23
  def initialize(config_class: Class.new(Config), config_attributes: [])
@@ -77,9 +79,12 @@ class Sinclair
77
79
  #
78
80
  # config.respond_to? :active
79
81
  # # returns true
80
- def add_configs(*attributes)
81
- config_class.attr_reader(*attributes)
82
- config_attributes.concat(attributes.map(&:to_sym))
82
+ def add_configs(*args)
83
+ builder = MethodsBuilder.new(config_class, *args)
84
+
85
+ builder.build
86
+
87
+ config_attributes.concat(builder.config_names.map(&:to_sym))
83
88
  end
84
89
 
85
90
  # Set the values in the config
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Sinclair
4
+ class ConfigFactory
5
+ # @api private
6
+ #
7
+ # Class responsible for adding method to configuration
8
+ # classes
9
+ class MethodsBuilder < Sinclair
10
+ # @param klass [Class] class inheriting from {Sinclair::Config}
11
+ # that will receive the methods
12
+ # @overload initialize(klass, *names, default)
13
+ # @param names [Array<Symbol,String>] List of configuration names
14
+ # to be added
15
+ # @param default [Hash] Configurations that will receive a default
16
+ # value when not configured
17
+ def initialize(klass, *names)
18
+ super(klass)
19
+
20
+ @names = names
21
+ @defaults = names.find { |arg| arg.is_a?(Hash) } || {}
22
+ names.delete(defaults)
23
+ end
24
+
25
+ # Build the methods in config class
26
+ #
27
+ # Methods will be attribute readers that, when an attribute
28
+ # (instance variable) has never been defined, a default value
29
+ # is returned
30
+ #
31
+ # Setting an instance variable to nil will not return default
32
+ # value.
33
+ #
34
+ # If default value is required, {Sinclair::Configurable#reset_config}
35
+ # should be called
36
+ #
37
+ # @return (see Sinclair#build)
38
+ #
39
+ # @see Sinclair#build
40
+ def build
41
+ config_hash.each do |method, value|
42
+ add_method(method, cached: :full) { value }
43
+ end
44
+
45
+ super
46
+ end
47
+
48
+ # Returns the name of all configs defined by {MethodsBuilder}
49
+ #
50
+ # @return [Array<String,Symbol>]
51
+ def config_names
52
+ config_hash.keys
53
+ end
54
+
55
+ private
56
+
57
+ attr_reader :names, :defaults
58
+
59
+ # @private
60
+ #
61
+ # Builds the final config hash
62
+ #
63
+ # Config hash merges defauls config hashs
64
+ # with {#name_as_hash}
65
+ #
66
+ # @return [Hash]
67
+ def config_hash
68
+ @config_hash ||= names_as_hash.merge!(defaults)
69
+ end
70
+
71
+ # @private
72
+ #
73
+ # Builds a hash with nil values from config names
74
+ #
75
+ # @return [Hash]
76
+ def names_as_hash
77
+ Hash[names.map { |*name| name }]
78
+ end
79
+ end
80
+ end
81
+ end
@@ -17,7 +17,8 @@ class Sinclair
17
17
  # class MyConfigurable
18
18
  # extend Sinclair::Configurable
19
19
  #
20
- # configurable_with :host, :port
20
+ # # port is defaulted to 80
21
+ # configurable_with :host, port: 80
21
22
  # end
22
23
  #
23
24
  # MyConfigurable.configure do
@@ -31,12 +32,31 @@ class Sinclair
31
32
  # MyConfigurable.config.port
32
33
  # # returns 5555
33
34
  #
34
- # MyConfigurable.reset
35
+ # MyConfigurable.reset_config
35
36
  #
36
37
  # MyConfigurable.config.host
37
38
  # # returns nil
39
+ #
40
+ # MyConfigurable.config.port
41
+ # # returns 80
38
42
  module Configurable
39
- delegate :config, :reset_config, :configure, to: :config_factory
43
+ # (see ConfigFactory#config)
44
+ # @see ConfigFactory#config
45
+ def config
46
+ config_factory.config
47
+ end
48
+
49
+ # (see ConfigFactory#reset_config)
50
+ # @see ConfigFactory#reset_config
51
+ def reset_config
52
+ config_factory.reset_config
53
+ end
54
+
55
+ # (see ConfigFactory#configure)
56
+ # @see ConfigFactory#configure
57
+ def configure(&block)
58
+ config_factory.configure(&block)
59
+ end
40
60
 
41
61
  protected
42
62
 
@@ -64,7 +84,7 @@ class Sinclair
64
84
 
65
85
  private
66
86
 
67
- # @visibility public
87
+ # @!visibility public
68
88
  #
69
89
  # Adds a configuration option to config class
70
90
  #
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Sinclair
4
- VERSION = '1.3.1'
4
+ VERSION = '1.3.2'
5
5
  end
@@ -36,8 +36,7 @@ describe Sinclair::Configurable do
36
36
  end
37
37
 
38
38
  it 'resets configuration port' do
39
- expect(MyConfigurable.config.port)
40
- .to be_nil
39
+ expect(MyConfigurable.config.port).to eq(80)
41
40
  end
42
41
  end
43
42
  end
@@ -27,8 +27,11 @@ describe Sinclair::Configurable do
27
27
  before { MyConfigurable.reset_config }
28
28
 
29
29
  it 'returns initial value for host' do
30
- expect(MyConfigurable.config.host)
31
- .to be_nil
30
+ expect(MyConfigurable.config.host).to be_nil
31
+ end
32
+
33
+ it 'returns initial value for port' do
34
+ expect(MyConfigurable.config.port).to eq(80)
32
35
  end
33
36
  end
34
37
  end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Sinclair::ConfigFactory::MethodsBuilder do
6
+ describe '#build' do
7
+ let(:config_class) { Class.new(Sinclair::Config) }
8
+ let(:config) { config_class.new }
9
+ let(:code_block) { proc { builder.build } }
10
+
11
+ let(:setter_block) do
12
+ proc do |value|
13
+ config.instance_variable_set(:@name, value)
14
+ end
15
+ end
16
+
17
+ context 'when not initializing defaults' do
18
+ subject(:builder) { described_class.new(config_class, :name, 'password') }
19
+
20
+ it_behaves_like 'a config methods builder adding config'
21
+
22
+ it 'does not set a default value' do
23
+ code_block.call
24
+
25
+ expect(config.name).to be_nil
26
+ end
27
+ end
28
+
29
+ context 'when initializing defaults' do
30
+ subject(:builder) do
31
+ described_class.new(
32
+ config_class, name: 'Bobby', 'password' => 'abcdef'
33
+ )
34
+ end
35
+
36
+ it_behaves_like 'a config methods builder adding config'
37
+
38
+ it 'sets a default value' do
39
+ code_block.call
40
+
41
+ expect(config.name).to eq('Bobby')
42
+ end
43
+ end
44
+
45
+ context 'when mixing names and hash' do
46
+ subject(:builder) do
47
+ described_class.new(
48
+ config_class, :name, 'password' => 'abcdef'
49
+ )
50
+ end
51
+
52
+ it_behaves_like 'a config methods builder adding config'
53
+
54
+ it 'does not set a default value' do
55
+ code_block.call
56
+
57
+ expect(config.name).to be_nil
58
+ end
59
+
60
+ context 'when name and hash define same config' do
61
+ subject(:builder) do
62
+ described_class.new(
63
+ config_class, :name, name: 'Bobby'
64
+ )
65
+ end
66
+
67
+ it_behaves_like 'a config methods builder adding config'
68
+
69
+ it 'sets a default value' do
70
+ code_block.call
71
+
72
+ expect(config.name).to eq('Bobby')
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -81,46 +81,23 @@ describe Sinclair::ConfigFactory do
81
81
  end
82
82
 
83
83
  describe '#add_configs' do
84
- it 'adds reader to config' do
85
- expect { factory.add_configs(:name) }
86
- .to add_method(:name).to(factory.config)
87
- end
88
-
89
- it 'does not add setter to config' do
90
- expect { factory.add_configs(:name) }
91
- .not_to add_method(:name=).to(factory.config)
92
- end
93
-
94
- it 'does not change Sinclair::Config class' do
95
- expect { factory.add_configs(:name) }
96
- .not_to add_method(:name).to(Sinclair::Config.new)
97
- end
84
+ let(:config) { factory.config }
98
85
 
99
- it 'allows config_builder to handle method missing' do
100
- factory.add_configs(:name)
101
- expect { factory.configure { name 'John' } }.not_to raise_error
86
+ let(:code_block) do
87
+ proc { factory.instance_eval(&method_call) }
102
88
  end
103
89
 
104
- it 'changes subclasses of config' do
105
- expect { factory.add_configs(:name) }
106
- .to add_method(:name).to(factory.child.config)
90
+ let(:setter_block) do
91
+ proc { |value| factory.configure { name value } }
107
92
  end
108
93
 
109
- it 'does not mess with parent config_builder' do
110
- factory.child.add_configs(:name)
111
- expect { factory.configure { name 'John' } }
112
- .to raise_error(NoMethodError)
113
- end
94
+ it_behaves_like 'a config factory adding config' do
95
+ let(:method_call) { proc { add_configs(:name) } }
114
96
 
115
- context 'when initializing with custom config class' do
116
- it do
117
- expect { factory.add_configs(:name) }
118
- .to add_method(:name).to(factory.config)
119
- end
97
+ it 'does not set a default value' do
98
+ code_block.call
120
99
 
121
- it 'does not change other config classes' do
122
- expect { factory.add_configs(:name) }
123
- .not_to add_method(:name).to(other_factory.config)
100
+ expect(factory.config.name).to be_nil
124
101
  end
125
102
  end
126
103
 
@@ -130,30 +107,33 @@ describe Sinclair::ConfigFactory do
130
107
  factory.reset_config
131
108
  expect(factory.config).to be_a(Sinclair::Config)
132
109
  end
110
+
111
+ context 'when passing a hash' do
112
+ it_behaves_like 'a config factory adding config' do
113
+ let(:method_call) { proc { add_configs(name: 'Bobby') } }
114
+
115
+ it 'sets a default value' do
116
+ code_block.call
117
+
118
+ expect(factory.config.name).to eq('Bobby')
119
+ end
120
+ end
121
+ end
133
122
  end
134
123
 
135
124
  describe '#configure' do
136
- before { factory.add_configs(:user, 'password') }
125
+ context 'when factory was not initialized with defaults' do
126
+ before { factory.add_configs(:user, 'password') }
137
127
 
138
- it do
139
- expect { factory.configure { |c| c.user 'Bob' } }
140
- .to change(config, :user)
141
- .from(nil).to('Bob')
128
+ it_behaves_like 'configure a config'
142
129
  end
143
130
 
144
- context 'when it was defined using string' do
145
- it do
146
- expect { factory.configure { |c| c.password '123456' } }
147
- .to change(config, :password)
148
- .from(nil).to('123456')
131
+ context 'when factory initialized with defaults' do
132
+ before do
133
+ factory.add_configs(user: 'Jack', 'password' => 'abcdef')
149
134
  end
150
- end
151
135
 
152
- context 'when calling a method that was not defined' do
153
- it do
154
- expect { factory.configure { |c| c.nope '123456' } }
155
- .to raise_error(NoMethodError)
156
- end
136
+ it_behaves_like 'configure a config'
157
137
  end
158
138
  end
159
139
 
@@ -3,5 +3,6 @@
3
3
  class MyConfigurable
4
4
  extend Sinclair::Configurable
5
5
 
6
- configurable_with :host, :port
6
+ # port is defaulted to 80
7
+ configurable_with :host, port: 80
7
8
  end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ shared_examples 'a config methods builder adding config' do
4
+ it 'adds reader to config' do
5
+ expect(&code_block).to add_method(:name).to(config)
6
+ end
7
+
8
+ it 'does not add setter to config' do
9
+ expect(&code_block)
10
+ .not_to add_method(:name=).to(config)
11
+ end
12
+
13
+ it 'does not change Sinclair::Config class' do
14
+ expect(&code_block)
15
+ .not_to add_method(:name).to(Sinclair::Config)
16
+ end
17
+
18
+ it 'allows config_builder to handle method missing' do
19
+ code_block.call
20
+
21
+ expect { setter_block.call('John') }
22
+ .not_to raise_error
23
+ end
24
+
25
+ it 'adds reader for configuration' do
26
+ code_block.call
27
+ setter_block.call('John')
28
+
29
+ expect(config.name).to eq('John')
30
+ end
31
+
32
+ it 'adds reader for configuration accepting nil values' do
33
+ code_block.call
34
+ setter_block.call('John')
35
+ setter_block.call(nil)
36
+
37
+ expect(config.name).to be_nil
38
+ end
39
+ end
40
+
41
+ shared_examples 'a config factory adding config' do
42
+ it_behaves_like 'a config methods builder adding config'
43
+
44
+ it 'changes subclasses of config' do
45
+ expect(&code_block)
46
+ .to add_method(:name).to(factory.child.config)
47
+ end
48
+
49
+ it 'does not mess with parent config_builder' do
50
+ factory.child.instance_eval(&method_call)
51
+ expect { factory.configure { name 'John' } }
52
+ .to raise_error(NoMethodError)
53
+ end
54
+
55
+ context 'when initializing with custom config class' do
56
+ it do
57
+ expect(&code_block)
58
+ .to add_method(:name).to(factory.config)
59
+ end
60
+
61
+ it 'does not change other config classes' do
62
+ expect(&code_block)
63
+ .not_to add_method(:name).to(other_factory.config)
64
+ end
65
+ end
66
+ end
67
+
68
+ shared_examples 'configure a config' do
69
+ it 'sets value on config' do
70
+ expect { factory.configure { |c| c.user 'Bob' } }
71
+ .to change(config, :user).to('Bob')
72
+ end
73
+
74
+ context 'when re-seting the value to nil' do
75
+ before { factory.configure { |c| c.user 'Bob' } }
76
+
77
+ it 'sets nil value on config' do
78
+ expect { factory.configure { |c| c.user nil } }
79
+ .to change(config, :user).to(nil)
80
+ end
81
+ end
82
+
83
+ context 'when calling a method that was not defined' do
84
+ it do
85
+ expect { factory.configure { |c| c.nope '123456' } }
86
+ .to raise_error(NoMethodError)
87
+ end
88
+ end
89
+
90
+ context 'when it was defined using string' do
91
+ it do
92
+ expect { factory.configure { |c| c.password '123456' } }
93
+ .to change(config, :password)
94
+ .to('123456')
95
+ end
96
+ end
97
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sinclair
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.1
4
+ version: 1.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - DarthJee
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-06-17 00:00:00.000000000 Z
11
+ date: 2019-06-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -189,6 +189,7 @@ files:
189
189
  - lib/sinclair/config.rb
190
190
  - lib/sinclair/config_builder.rb
191
191
  - lib/sinclair/config_factory.rb
192
+ - lib/sinclair/config_factory/methods_builder.rb
192
193
  - lib/sinclair/configurable.rb
193
194
  - lib/sinclair/matchers.rb
194
195
  - lib/sinclair/matchers/add_method.rb
@@ -220,6 +221,7 @@ files:
220
221
  - spec/integration/yard/sinclair/options_parser_spec.rb
221
222
  - spec/integration/yard/sinclair_spec.rb
222
223
  - spec/lib/sinclair/config_builder_spec.rb
224
+ - spec/lib/sinclair/config_factory/methods_builder_spec.rb
223
225
  - spec/lib/sinclair/config_factory_spec.rb
224
226
  - spec/lib/sinclair/configurable_spec.rb
225
227
  - spec/lib/sinclair/matchers/add_method_spec.rb
@@ -252,6 +254,7 @@ files:
252
254
  - spec/support/models/purchase.rb
253
255
  - spec/support/models/server.rb
254
256
  - spec/support/models/validator_builder.rb
257
+ - spec/support/shared_examples/config_factory.rb
255
258
  - spec/support/shared_examples/method_definition.rb
256
259
  homepage: https://github.com/darthjee/sinclair
257
260
  licenses: []