sinclair 1.5.0 → 1.5.1
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 +115 -28
- data/config/yardstick.yml +1 -0
- data/lib/sinclair.rb +2 -1
- data/lib/sinclair/env_settable.rb +65 -0
- data/lib/sinclair/env_settable/builder.rb +63 -0
- data/lib/sinclair/version.rb +1 -1
- data/spec/integration/readme/sinclair/env_settable_spec.rb +21 -0
- data/spec/integration/readme/sinclair/matchers_spec.rb +12 -1
- data/spec/integration/readme/sinclair_spec.rb +34 -0
- data/spec/integration/yard/sinclair/env_settable_spec.rb +45 -0
- data/spec/lib/sinclair/env_settable/builder_spec.rb +35 -0
- data/spec/lib/sinclair/env_settable_spec.rb +26 -0
- data/spec/spec_helper.rb +2 -1
- data/spec/support/models/app_client.rb +7 -0
- data/spec/support/models/default_value.rb +8 -3
- data/spec/support/models/env_settings.rb +22 -0
- data/spec/support/models/host_config.rb +9 -0
- data/spec/support/models/my_app_client.rb +9 -0
- data/spec/support/models/service_client.rb +26 -0
- data/spec/support/shared_examples/env_settable.rb +43 -0
- metadata +14 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 82efd1a6383697b8f2a0bbc803c27f21f87e47dbeca8536c55ebeb7efc097cf9
|
4
|
+
data.tar.gz: 301b644a37ca5227dc0f8247bbf46ba1988b71b6d157ed2f21e19e3f6c20a957
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d22f829400b914d4c297eea101bc88f1676ad9febf7f76ca703a090553e0756d97af9889d9a93debd81b820a3aacd4ff969bbfbb9015c43a0eb7a9646ceb345f
|
7
|
+
data.tar.gz: 53c0b4d4e8d480577ee93d7e0436f6ee1d35d47208a1e363a3d6672f88894d9c3debc4c11804b226372690f6d5afa69793c08e49d855d135820cd940ec11ed0e
|
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.5.
|
17
|
+
https://www.rubydoc.info/gems/sinclair/1.5.1
|
18
18
|
|
19
19
|
Installation
|
20
20
|
---------------
|
@@ -37,7 +37,7 @@ Installation
|
|
37
37
|
Usage
|
38
38
|
---------------
|
39
39
|
# Sinclair
|
40
|
-
Sinclair can
|
40
|
+
Sinclair can actually be used in several ways, as a stand alone object capable of
|
41
41
|
adding methods to your class on the fly, as a builder inside a class method
|
42
42
|
or by extending it for more complex logics
|
43
43
|
|
@@ -52,12 +52,17 @@ or by extending it for more complex logics
|
|
52
52
|
|
53
53
|
builder.add_method(:twenty, '10 + 10')
|
54
54
|
builder.add_method(:eighty) { 4 * twenty }
|
55
|
+
builder.add_class_method(:one_hundred) { 100 }
|
56
|
+
builder.add_class_method(:one_hundred_twenty, 'one_hundred + 20')
|
55
57
|
builder.build
|
56
58
|
|
57
59
|
instance = Clazz.new
|
58
60
|
|
59
61
|
puts "Twenty => #{instance.twenty}" # Twenty => 20
|
60
62
|
puts "Eighty => #{instance.eighty}" # Eighty => 80
|
63
|
+
|
64
|
+
puts "One Hundred => #{Clazz.one_hundred}" # One Hundred => 100
|
65
|
+
puts "One Hundred => #{Clazz.one_hundred_twenty}" # One Hundred Twenty => 120
|
61
66
|
```
|
62
67
|
|
63
68
|
## Builder in class method:
|
@@ -120,6 +125,43 @@ or by extending it for more complex logics
|
|
120
125
|
person.email # returns 'lord@bob.com'
|
121
126
|
```
|
122
127
|
|
128
|
+
```ruby
|
129
|
+
module EnvSettings
|
130
|
+
def env_prefix(new_prefix=nil)
|
131
|
+
@env_prefix = new_prefix if new_prefix
|
132
|
+
@env_prefix
|
133
|
+
end
|
134
|
+
|
135
|
+
def from_env(*method_names)
|
136
|
+
builder = Sinclair.new(self)
|
137
|
+
|
138
|
+
method_names.each do |method_name|
|
139
|
+
env_key = [env_prefix, method_name].compact.join('_').upcase
|
140
|
+
|
141
|
+
builder.add_class_method(method_name, cached: true) do
|
142
|
+
ENV[env_key]
|
143
|
+
end
|
144
|
+
|
145
|
+
builder.build
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
class MyServerConfig
|
151
|
+
extend EnvSettings
|
152
|
+
|
153
|
+
env_prefix :server
|
154
|
+
|
155
|
+
from_env :host, :port
|
156
|
+
end
|
157
|
+
|
158
|
+
ENV['SERVER_HOST'] = 'myserver.com'
|
159
|
+
ENV['SERVER_PORT'] = '9090'
|
160
|
+
|
161
|
+
MyServerConfig.host # returns 'myserver.com'
|
162
|
+
MyServerConfig.port # returns '9090'
|
163
|
+
```
|
164
|
+
|
123
165
|
## Extending the builder
|
124
166
|
|
125
167
|
```ruby
|
@@ -366,57 +408,101 @@ Configurations can also be done through custom classes
|
|
366
408
|
Client.config.url # returns 'http://interstella.com:8080'
|
367
409
|
```
|
368
410
|
|
411
|
+
# Sinclair::Settable
|
412
|
+
|
413
|
+
Settable allows classes to extract configuration from environments through
|
414
|
+
a simple meta-programable way
|
415
|
+
|
416
|
+
```ruby
|
417
|
+
class ServiceClient
|
418
|
+
extend Sinclair::EnvSettable
|
419
|
+
attr_reader :username, :password, :host, :port
|
420
|
+
|
421
|
+
settings_prefix 'SERVICE'
|
422
|
+
|
423
|
+
with_settings :username, :password, port: 80, hostname: 'my-host.com'
|
424
|
+
|
425
|
+
def self.default
|
426
|
+
@default ||= new
|
427
|
+
end
|
428
|
+
|
429
|
+
def initialize(
|
430
|
+
username: self.class.username,
|
431
|
+
password: self.class.password,
|
432
|
+
port: self.class.port,
|
433
|
+
hostname: self.class.hostname
|
434
|
+
)
|
435
|
+
@username = username
|
436
|
+
@password = password
|
437
|
+
@port = port
|
438
|
+
@hostname = hostname
|
439
|
+
end
|
440
|
+
end
|
441
|
+
|
442
|
+
ENV['SERVICE_USERNAME'] = 'my-login'
|
443
|
+
ENV['SERVICE_HOSTNAME'] = 'host.com'
|
444
|
+
|
445
|
+
ServiceClient.default # returns #<ServiceClient:0x0000556fa1b366e8 @username="my-login", @password=nil, @port=80, @hostname="host.com">'
|
446
|
+
```
|
447
|
+
|
369
448
|
RSspec matcher
|
370
449
|
---------------
|
371
450
|
|
372
451
|
You can use the provided matcher to check that your builder is adding a method correctly
|
373
452
|
|
374
453
|
```ruby
|
375
|
-
|
376
454
|
class DefaultValue
|
377
455
|
delegate :build, to: :builder
|
378
|
-
attr_reader :klass, :method, :value
|
456
|
+
attr_reader :klass, :method, :value, :class_method
|
379
457
|
|
380
|
-
def initialize(klass, method, value)
|
458
|
+
def initialize(klass, method, value, class_method: false)
|
381
459
|
@klass = klass
|
382
460
|
@method = method
|
383
461
|
@value = value
|
462
|
+
@class_method = class_method
|
384
463
|
end
|
385
464
|
|
386
465
|
private
|
387
466
|
|
388
467
|
def builder
|
389
468
|
@builder ||= Sinclair.new(klass).tap do |b|
|
390
|
-
|
469
|
+
if class_method
|
470
|
+
b.add_class_method(method) { value }
|
471
|
+
else
|
472
|
+
b.add_method(method) { value }
|
473
|
+
end
|
391
474
|
end
|
392
475
|
end
|
393
476
|
end
|
394
477
|
|
395
|
-
|
396
|
-
|
397
|
-
config.include Sinclair::Matchers
|
398
|
-
end
|
478
|
+
RSpec.describe Sinclair::Matchers do
|
479
|
+
subject(:builder_class) { DefaultValue }
|
399
480
|
|
400
|
-
|
401
|
-
let(:
|
402
|
-
let(:
|
403
|
-
let(:
|
404
|
-
let(:
|
405
|
-
let(:instance) { klass.new }
|
481
|
+
let(:klass) { Class.new }
|
482
|
+
let(:method) { :the_method }
|
483
|
+
let(:value) { Random.rand(100) }
|
484
|
+
let(:builder) { builder_class.new(klass, method, value) }
|
485
|
+
let(:instance) { klass.new }
|
406
486
|
|
407
487
|
context 'when the builder runs' do
|
408
488
|
it do
|
409
|
-
expect
|
410
|
-
described_class.new(klass, method, value).build
|
411
|
-
end.to add_method(method).to(instance)
|
489
|
+
expect { builder.build }.to add_method(method).to(instance)
|
412
490
|
end
|
413
491
|
end
|
414
492
|
|
415
493
|
context 'when the builder runs' do
|
416
494
|
it do
|
417
|
-
expect
|
418
|
-
|
419
|
-
|
495
|
+
expect { builder.build }.to add_method(method).to(klass)
|
496
|
+
end
|
497
|
+
end
|
498
|
+
|
499
|
+
context 'when adding class methods' do
|
500
|
+
subject(:builder) { builder_class.new(klass, method, value, class_method: true) }
|
501
|
+
|
502
|
+
context 'when the builder runs' do
|
503
|
+
it do
|
504
|
+
expect { builder.build }.to add_class_method(method).to(klass)
|
505
|
+
end
|
420
506
|
end
|
421
507
|
end
|
422
508
|
end
|
@@ -428,13 +514,14 @@ You can use the provided matcher to check that your builder is adding a method c
|
|
428
514
|
```
|
429
515
|
|
430
516
|
```string
|
431
|
-
|
432
|
-
DefaultValue
|
517
|
+
Sinclair::Matchers
|
433
518
|
when the builder runs
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
519
|
+
should add method 'the_method' to #<Class:0x000055e5d9b7f150> instances
|
520
|
+
when the builder runs
|
521
|
+
should add method 'the_method' to #<Class:0x000055e5d9b8c0a8> instances
|
522
|
+
when adding class methods
|
523
|
+
when the builder runs
|
524
|
+
should add method class_method 'the_method' to #<Class:0x000055e5d9b95d88>
|
438
525
|
```
|
439
526
|
|
440
527
|
Projects Using
|
data/config/yardstick.yml
CHANGED
@@ -32,6 +32,7 @@ rules:
|
|
32
32
|
exclude:
|
33
33
|
- Sinclair::Config::MethodsBuilder#initialize
|
34
34
|
- Sinclair::ConfigFactory#initialize
|
35
|
+
- Sinclair::EnvSettable::Builder#initialize
|
35
36
|
- Sinclair::Matchers::AddClassMethodTo#initialize
|
36
37
|
- Sinclair::Matchers::AddInstanceMethodTo#instance
|
37
38
|
- Sinclair::Matchers::AddMethod#initialize
|
data/lib/sinclair.rb
CHANGED
@@ -25,7 +25,7 @@ require 'active_support/all'
|
|
25
25
|
# instance.value = 20
|
26
26
|
# instance.value # returns 20
|
27
27
|
#
|
28
|
-
# @example
|
28
|
+
# @example Using cache
|
29
29
|
# module DefaultValueable
|
30
30
|
# def default_reader(*methods, value:, accept_nil: false)
|
31
31
|
# DefaultValueBuilder.new(
|
@@ -91,6 +91,7 @@ class Sinclair
|
|
91
91
|
autoload :MethodBuilder, 'sinclair/method_builder'
|
92
92
|
autoload :MethodDefinition, 'sinclair/method_definition'
|
93
93
|
autoload :MethodDefinitions, 'sinclair/method_definitions'
|
94
|
+
autoload :EnvSettable, 'sinclair/env_settable'
|
94
95
|
|
95
96
|
include OptionsParser
|
96
97
|
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Sinclair
|
4
|
+
# @api public
|
5
|
+
# @author darthjee
|
6
|
+
#
|
7
|
+
# Module to be extended allowing configurations from environment
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# class MyAppClient
|
11
|
+
# extend Sinclair::EnvSettable
|
12
|
+
#
|
13
|
+
# settings_prefix 'MY_APP'
|
14
|
+
#
|
15
|
+
# with_settings :username, :password, host: 'my-host.com'
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# ENV['MY_APP_USERNAME'] = 'my_login'
|
19
|
+
#
|
20
|
+
# MyAppClient.username # returns 'my_login'
|
21
|
+
# MyAppClient.password # returns nil
|
22
|
+
# MyAppClient.host # returns 'my-host.com'
|
23
|
+
#
|
24
|
+
# ENV['MY_APP_HOST'] = 'other-host.com'
|
25
|
+
#
|
26
|
+
# MyAppClient.host # returns 'other-host.com'
|
27
|
+
#
|
28
|
+
module EnvSettable
|
29
|
+
autoload :Builder, 'sinclair/env_settable/builder'
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
# @private
|
34
|
+
# @api public
|
35
|
+
# @visibility public
|
36
|
+
#
|
37
|
+
# Sets environment keys prefix
|
38
|
+
#
|
39
|
+
# @param prefix [String] prefix of the env keys
|
40
|
+
#
|
41
|
+
# @return [String]
|
42
|
+
#
|
43
|
+
# @example (see EnvSettable)
|
44
|
+
def settings_prefix(prefix)
|
45
|
+
@settings_prefix = prefix
|
46
|
+
end
|
47
|
+
|
48
|
+
# @private
|
49
|
+
# @api public
|
50
|
+
# @visibility public
|
51
|
+
#
|
52
|
+
# Adds settings
|
53
|
+
#
|
54
|
+
# @param settings_name [Array<Symbol,String>] Name of all settings
|
55
|
+
# to be added
|
56
|
+
# @param defaults [Hash] Settings with default values
|
57
|
+
#
|
58
|
+
# @return (see Sinclair#build)
|
59
|
+
#
|
60
|
+
# @example (see EnvSettable)
|
61
|
+
def with_settings(*settings_name, **defaults)
|
62
|
+
Builder.new(self, @settings_prefix, *settings_name, **defaults).build
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Sinclair
|
4
|
+
module EnvSettable
|
5
|
+
# @api private
|
6
|
+
# @author darthjee
|
7
|
+
#
|
8
|
+
# Env setting methods builder
|
9
|
+
#
|
10
|
+
# This builder does the magic of adding methods
|
11
|
+
# that will fetch variables from env or a default value
|
12
|
+
class Builder < Sinclair
|
13
|
+
# @param klass [Class] Class that will receive the methods
|
14
|
+
# @param prefix [String] Env keys prefix
|
15
|
+
# @param (see EnvSettable#with_settings)
|
16
|
+
def initialize(klass, prefix, *settings_name, **defaults)
|
17
|
+
super(klass, prefix: prefix)
|
18
|
+
|
19
|
+
@settings = Hash[settings_name.map { |name| [name] }]
|
20
|
+
|
21
|
+
@settings.merge!(defaults)
|
22
|
+
|
23
|
+
add_all_methods
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :settings
|
29
|
+
# @method settings
|
30
|
+
# @private
|
31
|
+
# @api private
|
32
|
+
#
|
33
|
+
# Settings map with default values
|
34
|
+
#
|
35
|
+
# @return [Hash<Symbol,Object>]
|
36
|
+
|
37
|
+
delegate :prefix, to: :options_object
|
38
|
+
# @method prefix
|
39
|
+
# @private
|
40
|
+
# @api private
|
41
|
+
#
|
42
|
+
# Env keys prefix
|
43
|
+
#
|
44
|
+
# @return [String]
|
45
|
+
|
46
|
+
# @private
|
47
|
+
# @api private
|
48
|
+
#
|
49
|
+
# Process all settings adding the methods
|
50
|
+
#
|
51
|
+
# @return (see settings)
|
52
|
+
def add_all_methods
|
53
|
+
settings.each do |name, value|
|
54
|
+
key = [prefix, name].compact.join('_').to_s.upcase
|
55
|
+
|
56
|
+
add_class_method(name) do
|
57
|
+
ENV[key] || value
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/sinclair/version.rb
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Sinclair::EnvSettable do
|
6
|
+
describe 'readme' do
|
7
|
+
let(:client) { ServiceClient.default }
|
8
|
+
let(:query) do
|
9
|
+
/#<ServiceClient:[^ ]* @username="my-login", @password=nil, @port=80, @hostname="host.com">/
|
10
|
+
end
|
11
|
+
|
12
|
+
before do
|
13
|
+
ENV['SERVICE_USERNAME'] = 'my-login'
|
14
|
+
ENV['SERVICE_HOSTNAME'] = 'host.com'
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'sets defaults values' do
|
18
|
+
expect(client.inspect.to_s).to match(query)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -3,10 +3,11 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
RSpec.describe Sinclair::Matchers do
|
6
|
+
subject(:builder_class) { DefaultValue }
|
7
|
+
|
6
8
|
let(:klass) { Class.new }
|
7
9
|
let(:method) { :the_method }
|
8
10
|
let(:value) { Random.rand(100) }
|
9
|
-
let(:builder_class) { DefaultValue }
|
10
11
|
let(:builder) { builder_class.new(klass, method, value) }
|
11
12
|
let(:instance) { klass.new }
|
12
13
|
|
@@ -21,4 +22,14 @@ RSpec.describe Sinclair::Matchers do
|
|
21
22
|
expect { builder.build }.to add_method(method).to(klass)
|
22
23
|
end
|
23
24
|
end
|
25
|
+
|
26
|
+
context 'when adding class methods' do
|
27
|
+
subject(:builder) { builder_class.new(klass, method, value, class_method: true) }
|
28
|
+
|
29
|
+
context 'when the builder runs' do
|
30
|
+
it do
|
31
|
+
expect { builder.build }.to add_class_method(method).to(klass)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
24
35
|
end
|
@@ -11,6 +11,8 @@ describe Sinclair do
|
|
11
11
|
before do
|
12
12
|
builder.add_method(:twenty, '10 + 10')
|
13
13
|
builder.add_method(:eighty) { 4 * twenty }
|
14
|
+
builder.add_class_method(:one_hundred) { 100 }
|
15
|
+
builder.add_class_method(:one_hundred_twenty, 'one_hundred + 20')
|
14
16
|
builder.build
|
15
17
|
end
|
16
18
|
|
@@ -21,6 +23,15 @@ describe Sinclair do
|
|
21
23
|
it 'knows how to add block defined methods' do
|
22
24
|
expect("Eighty => #{instance.eighty}").to eq('Eighty => 80')
|
23
25
|
end
|
26
|
+
|
27
|
+
it 'adds class method from block' do
|
28
|
+
expect("One Hundred => #{klass.one_hundred}").to eq('One Hundred => 100')
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'adds class method from string' do
|
32
|
+
expect("One Hundred Twenty => #{klass.one_hundred_twenty}")
|
33
|
+
.to eq('One Hundred Twenty => 120')
|
34
|
+
end
|
24
35
|
end
|
25
36
|
|
26
37
|
describe 'Stand Alone concern' do
|
@@ -63,6 +74,29 @@ describe Sinclair do
|
|
63
74
|
end
|
64
75
|
end
|
65
76
|
|
77
|
+
describe 'Class Stand Alone Concern' do
|
78
|
+
let(:host) { 'myserver.com' }
|
79
|
+
let(:port) { '9090' }
|
80
|
+
|
81
|
+
before do
|
82
|
+
ENV['SERVER_HOST'] = host
|
83
|
+
ENV['SERVER_PORT'] = port
|
84
|
+
end
|
85
|
+
|
86
|
+
after do
|
87
|
+
ENV.delete('SERVER_HOST')
|
88
|
+
ENV.delete('SERVER_PORT')
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'adds class method for host' do
|
92
|
+
expect(HostConfig.host).to eq(host)
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'adds class method for port' do
|
96
|
+
expect(HostConfig.port).to eq(port)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
66
100
|
describe 'DefaultValuable' do
|
67
101
|
subject(:server) { Server.new }
|
68
102
|
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Sinclair::EnvSettable do
|
6
|
+
describe '#yard' do
|
7
|
+
subject(:settable) { Class.new(MyAppClient) }
|
8
|
+
|
9
|
+
before do
|
10
|
+
ENV['MY_APP_USERNAME'] = 'my_login'
|
11
|
+
end
|
12
|
+
|
13
|
+
after do
|
14
|
+
ENV.delete('MY_APP_USERNAME')
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'retrieves username from env' do
|
18
|
+
expect(settable.username).to eq('my_login')
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'retrieves password from env' do
|
22
|
+
expect(settable.password).to be_nil
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'when defining defaults' do
|
26
|
+
it 'returns default value' do
|
27
|
+
expect(settable.host).to eq('my-host.com')
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'when setting the env variable' do
|
31
|
+
before do
|
32
|
+
ENV['MY_APP_HOST'] = 'other-host.com'
|
33
|
+
end
|
34
|
+
|
35
|
+
after do
|
36
|
+
ENV.delete('MY_APP_HOST')
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'retrieves host from env' do
|
40
|
+
expect(settable.host).to eq('other-host.com')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Sinclair::EnvSettable::Builder do
|
6
|
+
subject(:settable) { Class.new }
|
7
|
+
|
8
|
+
let(:username) { 'my_login' }
|
9
|
+
let(:password) { Random.rand(10_000).to_s }
|
10
|
+
|
11
|
+
let(:builder) do
|
12
|
+
described_class.new(settable, prefix, :username, :password, host: 'my-host.com')
|
13
|
+
end
|
14
|
+
|
15
|
+
before { builder.build }
|
16
|
+
|
17
|
+
context 'when not using prefix' do
|
18
|
+
let(:prefix) { nil }
|
19
|
+
|
20
|
+
let(:username_key) { 'USERNAME' }
|
21
|
+
let(:password_key) { 'PASSWORD' }
|
22
|
+
let(:host_key) { 'HOST' }
|
23
|
+
|
24
|
+
it_behaves_like 'settings reading from env'
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'when defining a prefix' do
|
28
|
+
let(:prefix) { 'MY_APP' }
|
29
|
+
let(:username_key) { 'MY_APP_USERNAME' }
|
30
|
+
let(:password_key) { 'MY_APP_PASSWORD' }
|
31
|
+
let(:host_key) { 'MY_APP_HOST' }
|
32
|
+
|
33
|
+
it_behaves_like 'settings reading from env'
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Sinclair::EnvSettable do
|
6
|
+
subject(:settable) { Class.new(AppClient) }
|
7
|
+
|
8
|
+
let(:username) { 'my_login' }
|
9
|
+
let(:password) { Random.rand(10_000).to_s }
|
10
|
+
|
11
|
+
let(:username_key) { 'USERNAME' }
|
12
|
+
let(:password_key) { 'PASSWORD' }
|
13
|
+
let(:host_key) { 'HOST' }
|
14
|
+
|
15
|
+
it_behaves_like 'settings reading from env'
|
16
|
+
|
17
|
+
context 'when defining a prefix' do
|
18
|
+
subject(:settable) { Class.new(MyAppClient) }
|
19
|
+
|
20
|
+
let(:username_key) { 'MY_APP_USERNAME' }
|
21
|
+
let(:password_key) { 'MY_APP_PASSWORD' }
|
22
|
+
let(:host_key) { 'MY_APP_HOST' }
|
23
|
+
|
24
|
+
it_behaves_like 'settings reading from env'
|
25
|
+
end
|
26
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -13,7 +13,8 @@ require 'sinclair/matchers'
|
|
13
13
|
require 'pry-nav'
|
14
14
|
|
15
15
|
support_files = File.expand_path('spec/support/**/*.rb')
|
16
|
-
|
16
|
+
|
17
|
+
Dir[support_files].sort.each { |file| require file }
|
17
18
|
|
18
19
|
RSpec.configure do |config|
|
19
20
|
config.run_all_when_everything_filtered = true
|
@@ -2,19 +2,24 @@
|
|
2
2
|
|
3
3
|
class DefaultValue
|
4
4
|
delegate :build, to: :builder
|
5
|
-
attr_reader :klass, :method, :value
|
5
|
+
attr_reader :klass, :method, :value, :class_method
|
6
6
|
|
7
|
-
def initialize(klass, method, value)
|
7
|
+
def initialize(klass, method, value, class_method: false)
|
8
8
|
@klass = klass
|
9
9
|
@method = method
|
10
10
|
@value = value
|
11
|
+
@class_method = class_method
|
11
12
|
end
|
12
13
|
|
13
14
|
private
|
14
15
|
|
15
16
|
def builder
|
16
17
|
@builder ||= Sinclair.new(klass).tap do |b|
|
17
|
-
|
18
|
+
if class_method
|
19
|
+
b.add_class_method(method) { value }
|
20
|
+
else
|
21
|
+
b.add_method(method) { value }
|
22
|
+
end
|
18
23
|
end
|
19
24
|
end
|
20
25
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EnvSettings
|
4
|
+
def env_prefix(new_prefix = nil)
|
5
|
+
@env_prefix = new_prefix if new_prefix
|
6
|
+
@env_prefix
|
7
|
+
end
|
8
|
+
|
9
|
+
def from_env(*method_names)
|
10
|
+
builder = Sinclair.new(self)
|
11
|
+
|
12
|
+
method_names.each do |method_name|
|
13
|
+
env_key = [env_prefix, method_name].compact.join('_').upcase
|
14
|
+
|
15
|
+
builder.add_class_method(method_name, cached: true) do
|
16
|
+
ENV[env_key]
|
17
|
+
end
|
18
|
+
|
19
|
+
builder.build
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ServiceClient
|
4
|
+
extend Sinclair::EnvSettable
|
5
|
+
attr_reader :username, :password, :host, :port
|
6
|
+
|
7
|
+
settings_prefix 'SERVICE'
|
8
|
+
|
9
|
+
with_settings :username, :password, port: 80, hostname: 'my-host.com'
|
10
|
+
|
11
|
+
def self.default
|
12
|
+
@default ||= new
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(
|
16
|
+
username: self.class.username,
|
17
|
+
password: self.class.password,
|
18
|
+
port: self.class.port,
|
19
|
+
hostname: self.class.hostname
|
20
|
+
)
|
21
|
+
@username = username
|
22
|
+
@password = password
|
23
|
+
@port = port
|
24
|
+
@hostname = hostname
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
shared_examples 'settings reading from env' do
|
4
|
+
before do
|
5
|
+
ENV[username_key] = username
|
6
|
+
ENV[password_key] = password
|
7
|
+
end
|
8
|
+
|
9
|
+
after do
|
10
|
+
ENV.delete(username_key)
|
11
|
+
ENV.delete(password_key)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'retrieves username from env' do
|
15
|
+
expect(settable.username).to eq(username)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'retrieves password from env' do
|
19
|
+
expect(settable.password).to eq(password)
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'when defining defaults' do
|
23
|
+
it 'returns default value' do
|
24
|
+
expect(settable.host).to eq('my-host.com')
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'when setting the env variable' do
|
28
|
+
let(:other_host) { 'other-host.com' }
|
29
|
+
|
30
|
+
before do
|
31
|
+
ENV[host_key] = other_host
|
32
|
+
end
|
33
|
+
|
34
|
+
after do
|
35
|
+
ENV.delete(host_key)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'retrieves host from env' do
|
39
|
+
expect(settable.host).to eq(other_host)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
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.5.
|
4
|
+
version: 1.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- DarthJee
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-09-
|
11
|
+
date: 2019-09-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -278,6 +278,8 @@ files:
|
|
278
278
|
- lib/sinclair/config_class.rb
|
279
279
|
- lib/sinclair/config_factory.rb
|
280
280
|
- lib/sinclair/configurable.rb
|
281
|
+
- lib/sinclair/env_settable.rb
|
282
|
+
- lib/sinclair/env_settable/builder.rb
|
281
283
|
- lib/sinclair/matchers.rb
|
282
284
|
- lib/sinclair/matchers/add_class_method.rb
|
283
285
|
- lib/sinclair/matchers/add_class_method_to.rb
|
@@ -301,6 +303,7 @@ files:
|
|
301
303
|
- spec/integration/readme/my_class_spec.rb
|
302
304
|
- spec/integration/readme/my_model_spec.rb
|
303
305
|
- spec/integration/readme/sinclair/configurable_spec.rb
|
306
|
+
- spec/integration/readme/sinclair/env_settable_spec.rb
|
304
307
|
- spec/integration/readme/sinclair/matchers_spec.rb
|
305
308
|
- spec/integration/readme/sinclair_spec.rb
|
306
309
|
- spec/integration/yard/my_builder_spec.rb
|
@@ -309,6 +312,7 @@ files:
|
|
309
312
|
- spec/integration/yard/sinclair/config_factory_spec.rb
|
310
313
|
- spec/integration/yard/sinclair/config_spec.rb
|
311
314
|
- spec/integration/yard/sinclair/configurable_spec.rb
|
315
|
+
- spec/integration/yard/sinclair/env_settable_spec.rb
|
312
316
|
- spec/integration/yard/sinclair/matchers/add_class_method_spec.rb
|
313
317
|
- spec/integration/yard/sinclair/matchers/add_class_method_to_spec.rb
|
314
318
|
- spec/integration/yard/sinclair/matchers/add_instance_method_spec.rb
|
@@ -321,6 +325,8 @@ files:
|
|
321
325
|
- spec/lib/sinclair/config_factory_spec.rb
|
322
326
|
- spec/lib/sinclair/config_spec.rb
|
323
327
|
- spec/lib/sinclair/configurable_spec.rb
|
328
|
+
- spec/lib/sinclair/env_settable/builder_spec.rb
|
329
|
+
- spec/lib/sinclair/env_settable_spec.rb
|
324
330
|
- spec/lib/sinclair/matchers/add_class_method_spec.rb
|
325
331
|
- spec/lib/sinclair/matchers/add_class_method_to_spec.rb
|
326
332
|
- spec/lib/sinclair/matchers/add_instance_method_spec.rb
|
@@ -338,6 +344,7 @@ files:
|
|
338
344
|
- spec/lib/sinclair_spec.rb
|
339
345
|
- spec/spec_helper.rb
|
340
346
|
- spec/support/fixture_helpers.rb
|
347
|
+
- spec/support/models/app_client.rb
|
341
348
|
- spec/support/models/app_config.rb
|
342
349
|
- spec/support/models/client.rb
|
343
350
|
- spec/support/models/default_value.rb
|
@@ -348,10 +355,13 @@ files:
|
|
348
355
|
- spec/support/models/dummy_config.rb
|
349
356
|
- spec/support/models/dummy_configurable.rb
|
350
357
|
- spec/support/models/dummy_options_parser.rb
|
358
|
+
- spec/support/models/env_settings.rb
|
359
|
+
- spec/support/models/host_config.rb
|
351
360
|
- spec/support/models/http_json_model.rb
|
352
361
|
- spec/support/models/http_person.rb
|
353
362
|
- spec/support/models/initial_valuer.rb
|
354
363
|
- spec/support/models/login_config.rb
|
364
|
+
- spec/support/models/my_app_client.rb
|
355
365
|
- spec/support/models/my_builder.rb
|
356
366
|
- spec/support/models/my_class.rb
|
357
367
|
- spec/support/models/my_concern.rb
|
@@ -364,10 +374,12 @@ files:
|
|
364
374
|
- spec/support/models/random_generator.rb
|
365
375
|
- spec/support/models/server.rb
|
366
376
|
- spec/support/models/server_config.rb
|
377
|
+
- spec/support/models/service_client.rb
|
367
378
|
- spec/support/models/validator_builder.rb
|
368
379
|
- spec/support/shared_examples/class_method_definition.rb
|
369
380
|
- spec/support/shared_examples/config.rb
|
370
381
|
- spec/support/shared_examples/config_factory.rb
|
382
|
+
- spec/support/shared_examples/env_settable.rb
|
371
383
|
- spec/support/shared_examples/instance_method_definition.rb
|
372
384
|
homepage: https://github.com/darthjee/sinclair
|
373
385
|
licenses: []
|