qonfig 0.1.0 → 0.2.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/.rubocop.yml +24 -3
- data/CHANGELOG.md +47 -1
- data/README.md +472 -19
- data/lib/qonfig/command_set.rb +26 -4
- data/lib/qonfig/commands/add_nested_option.rb +14 -11
- data/lib/qonfig/commands/add_option.rb +8 -3
- data/lib/qonfig/commands/compose.rb +7 -0
- data/lib/qonfig/commands/load_from_env/value_converter.rb +84 -0
- data/lib/qonfig/commands/load_from_env.rb +97 -0
- data/lib/qonfig/commands/load_from_self.rb +77 -0
- data/lib/qonfig/commands/load_from_yaml.rb +62 -0
- data/lib/qonfig/configurable.rb +108 -0
- data/lib/qonfig/data_set/class_builder.rb +32 -0
- data/lib/qonfig/data_set.rb +96 -5
- data/lib/qonfig/dsl.rb +48 -7
- data/lib/qonfig/error.rb +47 -1
- data/lib/qonfig/loaders/yaml.rb +34 -0
- data/lib/qonfig/settings/builder.rb +22 -0
- data/lib/qonfig/settings/key_guard.rb +75 -0
- data/lib/qonfig/settings/lock.rb +64 -0
- data/lib/qonfig/settings.rb +215 -54
- data/lib/qonfig/version.rb +2 -2
- data/lib/qonfig.rb +13 -1
- data/qonfig.gemspec +3 -3
- metadata +18 -9
- data/lib/qonfig/settings_builder.rb +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 364dfdc09c159ed886729491cc0d066f961b5be382b766d99d57705fca5f88d7
|
4
|
+
data.tar.gz: 9525458cf3d84fa9588ab48805cdb8a5ec0150278a7658986fb6325efcd2d191
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6cf8f8df874ebcb636f7862247ada545579f413c030b4d4dde51decb72ed18f38f5af3faa9c595e6cf741f25ab6fc8a09afef4c72133ced1448f12bbe76dbb96
|
7
|
+
data.tar.gz: 785f7e10238601b7f5be5c506d516004eee7d914b451e2a4c0a7e0aebf6257ca0003f19a52bad0c86f35c89713b4a837d5e175cbf71217cbd1f0de1a6950cc45
|
data/.rubocop.yml
CHANGED
@@ -5,8 +5,8 @@ AllCops:
|
|
5
5
|
DisplayStyleGuide: true
|
6
6
|
TargetRubyVersion: 2.5.1
|
7
7
|
Include:
|
8
|
-
- lib
|
9
|
-
- spec
|
8
|
+
- lib/**/*.rb
|
9
|
+
- spec/**/*.rb
|
10
10
|
Exclude:
|
11
11
|
- bin/**/*
|
12
12
|
- Gemfile
|
@@ -61,6 +61,9 @@ Lint/HandleExceptions:
|
|
61
61
|
Metrics/MethodLength:
|
62
62
|
Max: 20
|
63
63
|
|
64
|
+
Style/DoubleNegation:
|
65
|
+
Enabled: false
|
66
|
+
|
64
67
|
Style/EmptyCaseCondition:
|
65
68
|
Enabled: false
|
66
69
|
|
@@ -70,5 +73,23 @@ RSpec/ExampleLength:
|
|
70
73
|
RSpec/MultipleExpectations:
|
71
74
|
Enabled: false
|
72
75
|
|
76
|
+
Style/MultilineBlockChain:
|
77
|
+
Enabled: false
|
78
|
+
|
73
79
|
Metrics/AbcSize:
|
74
|
-
Max:
|
80
|
+
Max: 19
|
81
|
+
|
82
|
+
Metrics/CyclomaticComplexity:
|
83
|
+
Max: 10
|
84
|
+
|
85
|
+
Metrics/PerceivedComplexity:
|
86
|
+
Max: 10
|
87
|
+
|
88
|
+
Style/ClassAndModuleChildren:
|
89
|
+
Enabled: false
|
90
|
+
|
91
|
+
Lint/UnderscorePrefixedVariableName:
|
92
|
+
Enabled: false
|
93
|
+
|
94
|
+
Security/YAMLLoad:
|
95
|
+
Enabled: false
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,51 @@
|
|
1
1
|
# Changelog
|
2
2
|
All notable changes to this project will be documented in this file.
|
3
3
|
|
4
|
-
## [0.
|
4
|
+
## [0.2.0] - 2018-06-07
|
5
|
+
### Added
|
6
|
+
- Instant configuration via block `config = Config.new { |conf| <<your configuration code>> }`;
|
7
|
+
- `.load_from_env` command - an ability to define config settings by loading them from ENV variable;
|
8
|
+
- `.load_from_yaml` command - an ability to define config settings by loading them from a yaml file;
|
9
|
+
- `.load_from_self` command - an ability to load config definitions form the YAML
|
10
|
+
instructions written in the file where the config class is defined (`__END__` section);
|
11
|
+
- `#reload!` - an ability to reload config isntance after any config class changes and updates;
|
12
|
+
- `#clear!` - an ability to set all options to `nil`;
|
13
|
+
- `#dig` - an ability to fetch setting values in `Hash#dig` manner
|
14
|
+
(fails with `Qonfig::UnknownSettingError` when the required key does not exist);
|
15
|
+
- Settings as Predicates - an ability to check the boolean nature of the config setting by appending
|
16
|
+
the question mark symbol (`?`) at the end of setting name:
|
17
|
+
- `nil` and `false` setting values indicates `false`;
|
18
|
+
- other setting values indicates `true`;
|
19
|
+
- setting roots always returns `true`;
|
20
|
+
- examples:
|
21
|
+
- `config.settings.database.user # => nil`;
|
22
|
+
- `config.settings.database.user? # => false`;
|
23
|
+
- `config.settings.database.host # => 'google.com'`;
|
24
|
+
- `config.settings.database.host? # => true`;
|
25
|
+
- `config.settings.database? # => true (setting with nested option (setting root))`
|
26
|
+
- Support for ERB instructions in YAML;
|
27
|
+
- Support for `HashWithIndifferentAccess`-like behaviour;
|
28
|
+
- `Qonfig::Settings` instance method redefinition protection: the setting key can not
|
29
|
+
have a name that matches an any instance method name of `Qonfig::Settings`;
|
30
|
+
- Added `Qonfig::Configurable` mixin - configuration behaviour for any classes and modules
|
31
|
+
and their instances:
|
32
|
+
- all `Qonfig`-related features;
|
33
|
+
- different class-level and instance-level config objects;
|
34
|
+
- working class-level inheritance :);
|
35
|
+
- Full thread-safe implementation;
|
36
|
+
|
37
|
+
### Changed
|
38
|
+
- Superclass of `Qonfig::FrozenSettingsError` (it was `Qonfig::Error` before):
|
39
|
+
- `ruby >= 2.5` - inherited from `::FrozenError`;
|
40
|
+
- `ruby < 2.5` - inherited from `::RuntimeError`;
|
41
|
+
- `.setting` will raise exceptions immediately:
|
42
|
+
- `.setting(key, ...) { ... }` - if setting key has incompatible type;
|
43
|
+
- `.compose(config_class)`- if composed config class is not a subtype of `Qonfig::DataSet`;
|
44
|
+
|
45
|
+
### Fixed
|
46
|
+
- Recoursive hash representation with deep nested `Qonfig::Settings` values (infinite loop);
|
47
|
+
- Fixed re-assignment of the options with nested options (losing the nested options
|
48
|
+
due to the instance configuration). Now it causes `Qonfig::AmbigousSettingValueError`.
|
49
|
+
|
50
|
+
## [0.1.0] - 2018-05-18
|
5
51
|
- Release :)
|
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
# Qonfig · [](https://badge.fury.io/rb/qonfig) [](https://travis-ci.org/0exp/qonfig) [](https://coveralls.io/github/0exp/qonfig)
|
1
|
+
# Qonfig · [](https://badge.fury.io/rb/qonfig) [](https://travis-ci.org/0exp/qonfig) [](https://coveralls.io/github/0exp/qonfig?branch=master)
|
2
2
|
|
3
3
|
Config. Defined as a class. Used as an instance. Support for inheritance and composition.
|
4
|
-
Lazy instantiation. Command-style DSL. Extremely simple to define. Extremely simple to use. That's all.
|
4
|
+
Lazy instantiation. Thread-safe. Command-style DSL. Extremely simple to define. Extremely simple to use. That's all.
|
5
5
|
|
6
6
|
## Installation
|
7
7
|
|
@@ -12,7 +12,7 @@ gem 'qonfig'
|
|
12
12
|
```shell
|
13
13
|
$ bundle install
|
14
14
|
# --- or ---
|
15
|
-
gem install 'qonfig'
|
15
|
+
$ gem install 'qonfig'
|
16
16
|
```
|
17
17
|
|
18
18
|
```ruby
|
@@ -27,6 +27,13 @@ require 'qonfig'
|
|
27
27
|
- [Composition](#composition)
|
28
28
|
- [Hash representation](#hash-representation)
|
29
29
|
- [State freeze](#state-freeze)
|
30
|
+
- [Config reloading](#config-reloading) (reload config definitions and option values)
|
31
|
+
- [Clear options](#clear-options) (set to nil)
|
32
|
+
- [Settings as Predicates](#settings-as-predicates)
|
33
|
+
- [Load from YAML file](#load-from-yaml-file)
|
34
|
+
- [Load from ENV](#load-from-env)
|
35
|
+
- [Load from \_\_END\_\_](#load-from-__end__) (aka `load_from_self`)
|
36
|
+
- [Smart Mixin](#smart-mixin) (`Qonfig::Configurable`)
|
30
37
|
|
31
38
|
---
|
32
39
|
|
@@ -40,7 +47,6 @@ class Config < Qonfig::DataSet
|
|
40
47
|
# nested setting
|
41
48
|
setting :vendor_api do
|
42
49
|
setting :host, 'app.service.com'
|
43
|
-
setting :port, 12345
|
44
50
|
end
|
45
51
|
|
46
52
|
setting :enable_graphql, false
|
@@ -48,25 +54,38 @@ class Config < Qonfig::DataSet
|
|
48
54
|
# nested setting reopening
|
49
55
|
setting :vendor_api do
|
50
56
|
setting :user, 'test_user'
|
51
|
-
setting :password, 'test_password'
|
52
57
|
end
|
53
58
|
end
|
54
59
|
|
55
60
|
config = Config.new
|
56
61
|
|
62
|
+
# get option value via method
|
57
63
|
config.settings.project_id # => nil
|
58
|
-
config.settings.vendor_api.host # => '
|
59
|
-
config.settings.vendor_api.port # => 12345
|
64
|
+
config.settings.vendor_api.host # => 'app.service.com'
|
60
65
|
config.settings.vendor_api.user # => 'test_user'
|
61
|
-
config.settings.vendor_api.password # => 'test_password'
|
62
66
|
config.settings.enable_graphql # => false
|
63
67
|
|
68
|
+
# get option value via index (with indifferent (string / symbol / mixed) access)
|
64
69
|
config.settings[:project_id] # => nil
|
65
|
-
config.settings[:vendor_api][:host] # => '
|
66
|
-
config.settings[:vendor_api][:port] # => 12345
|
70
|
+
config.settings[:vendor_api][:host] # => 'app.service.com'
|
67
71
|
config.settings[:vendor_api][:user] # => 'test_user'
|
68
|
-
config.settings[:vendor_api][:password] # => 'test_password'
|
69
72
|
config.settings[:enable_graphql] # => false
|
73
|
+
|
74
|
+
# get option value via index (with indifferent (string / symbol / mixed) access)
|
75
|
+
config.settings['project_id'] # => nil
|
76
|
+
config.settings['vendor_api']['host'] # => 'app.service.com'
|
77
|
+
config.settings['vendor_api']['user'] # => 'test_user'
|
78
|
+
config.settings['enable_graphql'] # => false
|
79
|
+
|
80
|
+
# get option value directly via index (with indifferent access)
|
81
|
+
config['project_id'] # => nil
|
82
|
+
config['enable_graphql'] # => false
|
83
|
+
config[:project_id] # => nil
|
84
|
+
config[:enable_graphql] # => false
|
85
|
+
|
86
|
+
# get option value in Hash#dig manner (and fail when the required key does not exist)
|
87
|
+
config.dig(:vendor_api, :host) # => 'app.service.com' # (key exists)
|
88
|
+
config.dig(:vendor_api, :port) # => Qonfig::UnknownSettingError # (key does not exist)
|
70
89
|
```
|
71
90
|
|
72
91
|
---
|
@@ -89,7 +108,7 @@ end
|
|
89
108
|
|
90
109
|
config = Config.new
|
91
110
|
|
92
|
-
# configure via
|
111
|
+
# configure via proc
|
93
112
|
config.configure do |conf|
|
94
113
|
conf.enable_middlewares = true
|
95
114
|
conf.geo_api.provider = :yandex_maps
|
@@ -105,6 +124,13 @@ config.settings.testing.engine = :ultra_test
|
|
105
124
|
config.settings[:enable_middlewares] = true
|
106
125
|
config.settings[:geo_api][:provider] = :rambler_maps
|
107
126
|
config.settings[:testing][:engine] = :mega_test
|
127
|
+
|
128
|
+
# instant configuration via proc
|
129
|
+
config = Config.new do |conf|
|
130
|
+
conf.enable_middlewares = false
|
131
|
+
conf.geo_api.provider = :amazon_maps
|
132
|
+
conf.testing.engine = :crypto_test
|
133
|
+
end
|
108
134
|
```
|
109
135
|
|
110
136
|
---
|
@@ -191,7 +217,7 @@ class Config < Qonfig::DataSet
|
|
191
217
|
end
|
192
218
|
|
193
219
|
setting :adapter do
|
194
|
-
setting :default
|
220
|
+
setting :default, :memory_sync
|
195
221
|
end
|
196
222
|
|
197
223
|
setting :logger, Logger.new(STDOUT)
|
@@ -200,23 +226,107 @@ end
|
|
200
226
|
Config.new.to_h
|
201
227
|
|
202
228
|
{
|
203
|
-
serializers: {
|
204
|
-
json
|
205
|
-
hash
|
229
|
+
"serializers": {
|
230
|
+
"json" => { "engine" => :ok },
|
231
|
+
"hash" => { "engine" => :native },
|
206
232
|
},
|
207
|
-
adapter
|
208
|
-
logger
|
233
|
+
"adapter" => { "default" => :memory_sync },
|
234
|
+
"logger" => #<Logger:0x4b0d79fc>
|
209
235
|
}
|
210
236
|
```
|
211
237
|
|
212
238
|
---
|
213
239
|
|
240
|
+
### Config reloading
|
241
|
+
|
242
|
+
```ruby
|
243
|
+
class Config < Qonfig::DataSet
|
244
|
+
setting :db do
|
245
|
+
setting :adapter, 'postgresql'
|
246
|
+
end
|
247
|
+
|
248
|
+
setting :logger, Logger.new(STDOUT)
|
249
|
+
end
|
250
|
+
|
251
|
+
config = Config.new
|
252
|
+
|
253
|
+
config.settings.db.adapter # => 'postgresql'
|
254
|
+
config.settings.logger # => #<Logger:0x00007ff9>
|
255
|
+
|
256
|
+
config.configure { |conf| conf.logger = nil } # redefine some settings (will be reloaded)
|
257
|
+
|
258
|
+
# re-define and append settings
|
259
|
+
class Config
|
260
|
+
setting :db do
|
261
|
+
setting :adapter, 'mongoid' # re-define defaults
|
262
|
+
end
|
263
|
+
|
264
|
+
setting :enable_api, false # append new setting
|
265
|
+
end
|
266
|
+
|
267
|
+
# reload settings
|
268
|
+
config.reload!
|
269
|
+
|
270
|
+
config.settings.db.adapter # => 'mongoid'
|
271
|
+
config.settings.logger # => #<Logger:0x00007ff9> (reloaded from defaults)
|
272
|
+
config.settings.enable_api # => false (new setting)
|
273
|
+
|
274
|
+
# reload with instant configuration
|
275
|
+
config.reload! do |conf|
|
276
|
+
conf.enable_api = true # changed instantly
|
277
|
+
end
|
278
|
+
|
279
|
+
config.settings.db.adapter # => 'mongoid'
|
280
|
+
config.settings.logger = # => #<Logger:0x00007ff9>
|
281
|
+
config.settings.enable_api # => true # value from instant change
|
282
|
+
```
|
283
|
+
|
284
|
+
---
|
285
|
+
|
286
|
+
### Clear options
|
287
|
+
|
288
|
+
```ruby
|
289
|
+
class Config
|
290
|
+
setting :database do
|
291
|
+
setting :user
|
292
|
+
setting :password
|
293
|
+
end
|
294
|
+
|
295
|
+
setting :web_api do
|
296
|
+
setting :endpoint
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
config = Config.new do |conf|
|
301
|
+
conf.database.user = '0exp'
|
302
|
+
conf.database.password = 'test123'
|
303
|
+
|
304
|
+
conf.web_api.endpoint = '/api/'
|
305
|
+
end
|
306
|
+
|
307
|
+
config.settings.database.user # => '0exp'
|
308
|
+
config.settings.database.password # => 'test123'
|
309
|
+
config.settings.web_api.endpoint # => '/api'
|
310
|
+
|
311
|
+
# clear all options
|
312
|
+
config.clear!
|
313
|
+
|
314
|
+
config.settings.database.user # => nil
|
315
|
+
config.settings.database.password # => nil
|
316
|
+
config.settings.web_api.endpoint # => nil
|
317
|
+
```
|
318
|
+
|
319
|
+
---
|
320
|
+
|
214
321
|
### State freeze
|
215
322
|
|
216
323
|
```ruby
|
217
324
|
class Config < Qonfig::DataSet
|
218
325
|
setting :logger, Logger.new(STDOUT)
|
219
326
|
setting :worker, :sidekiq
|
327
|
+
setting :db do
|
328
|
+
setting :adapter, 'postgresql'
|
329
|
+
end
|
220
330
|
end
|
221
331
|
|
222
332
|
config = Config.new
|
@@ -224,14 +334,357 @@ config.freeze!
|
|
224
334
|
|
225
335
|
config.settings.logger = Logger.new(StringIO.new) # => Qonfig::FrozenSettingsError
|
226
336
|
config.settings.worker = :que # => Qonfig::FrozenSettingsError
|
337
|
+
config.settings.db.adapter = 'mongoid' # => Qonfig::FrozenSettingsError
|
338
|
+
|
339
|
+
config.reload! # => Qonfig::FrozenSettingsError
|
340
|
+
```
|
341
|
+
|
342
|
+
---
|
343
|
+
|
344
|
+
### Settings as Predicates
|
345
|
+
|
346
|
+
- predicate form: `?` at the end of setting name;
|
347
|
+
- `nil` and `false` setting values indicates `false`;
|
348
|
+
- other setting values indicates `true`;
|
349
|
+
- setting roots always returns `true`;
|
350
|
+
|
351
|
+
```ruby
|
352
|
+
class Config < Qonfig::DataSet
|
353
|
+
setting :database do
|
354
|
+
setting :user
|
355
|
+
setting :host, 'google.com'
|
356
|
+
|
357
|
+
setting :engine do
|
358
|
+
setting :driver, 'postgres'
|
359
|
+
end
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
config = Config.new
|
364
|
+
|
365
|
+
# predicates
|
366
|
+
config.settings.database.user? # => false (nil => false)
|
367
|
+
config.settings.database.host? # => true ('google.com' => true)
|
368
|
+
config.settings.database.engine.driver? # => true ('postgres' => true)
|
369
|
+
|
370
|
+
# setting roots always returns true
|
371
|
+
config.settings.database? # => true
|
372
|
+
config.settings.database.engine? # => ture
|
373
|
+
|
374
|
+
config.configure do |conf|
|
375
|
+
conf.database.user = '0exp'
|
376
|
+
conf.database.host = false
|
377
|
+
conf.database.engine.driver = true
|
378
|
+
end
|
379
|
+
|
380
|
+
# predicates
|
381
|
+
config.settings.database.user? # => true ('0exp' => true)
|
382
|
+
config.settings.database.host? # => false (false => false)
|
383
|
+
config.settings.database.engine.driver? # => true (true => true)
|
227
384
|
```
|
228
385
|
|
229
386
|
---
|
230
387
|
|
388
|
+
### Load from YAML file
|
389
|
+
|
390
|
+
- `:strict` mode (fail behaviour when the required yaml file doesnt exist):
|
391
|
+
- `true` (by default) - causes `Qonfig::FileNotFoundError`;
|
392
|
+
- `false` - do nothing, ignore current command;
|
393
|
+
|
394
|
+
```yaml
|
395
|
+
<!-- travis.yml -->
|
396
|
+
sudo: false
|
397
|
+
language: ruby
|
398
|
+
rvm:
|
399
|
+
- ruby-head
|
400
|
+
- jruby-head
|
401
|
+
```
|
402
|
+
|
403
|
+
```yaml
|
404
|
+
<!-- project.yml -->
|
405
|
+
enable_api: false
|
406
|
+
Sidekiq/Scheduler:
|
407
|
+
enable: true
|
408
|
+
```
|
409
|
+
|
410
|
+
```yaml
|
411
|
+
<!-- ruby_data.yml -->
|
412
|
+
version: <%= RUBY_VERSION %>
|
413
|
+
platform: <%= RUBY_PLATFORM %>
|
414
|
+
```
|
415
|
+
|
416
|
+
```ruby
|
417
|
+
class Config < Qonfig::DataSet
|
418
|
+
setting :ruby do
|
419
|
+
load_from_yaml 'ruby_data.yml'
|
420
|
+
end
|
421
|
+
|
422
|
+
setting :travis do
|
423
|
+
load_from_yaml 'travis.yml'
|
424
|
+
end
|
425
|
+
|
426
|
+
load_from_yaml 'project.yml'
|
427
|
+
end
|
428
|
+
|
429
|
+
config = Config.new
|
430
|
+
|
431
|
+
config.settings.travis.sudo # => false
|
432
|
+
config.settings.travis.language # => 'ruby'
|
433
|
+
config.settings.travis.rvm # => ['ruby-head', 'jruby-head']
|
434
|
+
config.settings.enable_api # => false
|
435
|
+
config.settings['Sidekiq/Scheduler']['enable'] #=> true
|
436
|
+
config.settings.ruby.version # => '2.5.1'
|
437
|
+
config.settings.ruby.platform # => 'x86_64-darwin17'
|
438
|
+
```
|
439
|
+
|
440
|
+
```ruby
|
441
|
+
# --- strict mode ---
|
442
|
+
class Config < Qonfig::DataSet
|
443
|
+
setting :nonexistent_yaml do
|
444
|
+
load_from_yaml 'unexistent_file.yml', strict: true # true by default
|
445
|
+
end
|
446
|
+
|
447
|
+
setting :another_key
|
448
|
+
end
|
449
|
+
|
450
|
+
Config.new # => Qonfig::FileNotFoundError
|
451
|
+
|
452
|
+
# --- non-strict mode ---
|
453
|
+
class Config < Qonfig::DataSet
|
454
|
+
settings :nonexistent_yaml do
|
455
|
+
load_from_yaml 'unexistent_file.yml', strict: false
|
456
|
+
end
|
457
|
+
|
458
|
+
setting :another_key
|
459
|
+
end
|
460
|
+
|
461
|
+
Config.new.to_h # => { "nonexistent_yaml" => {}, "another_key" => nil }
|
462
|
+
```
|
463
|
+
|
464
|
+
---
|
465
|
+
|
466
|
+
### Load from ENV
|
467
|
+
|
468
|
+
- `:convert_values` (`false` by default):
|
469
|
+
- `'t'`, `'T'`, `'true'`, `'TRUE'` - covnerts to `true`;
|
470
|
+
- `'f'`, `'F'`, `'false'`, `'FALSE'` - covnerts to `false`;
|
471
|
+
- `1`, `23` and etc - converts to `Integer`;
|
472
|
+
- `1.25`, `0.26` and etc - converts to `Float`;
|
473
|
+
- `1, 2, test`, `FALSE,Qonfig` (strings without quotes that contains at least one comma) -
|
474
|
+
converts to `Array` with recursively converted values;
|
475
|
+
- `'"please, test"'`, `"'test, please'"` (quoted strings) - converts to `String` without quotes;
|
476
|
+
- `:prefix` - load ENV variables which names starts with a prefix:
|
477
|
+
- `nil` (by default) - empty prefix;
|
478
|
+
- `Regexp` - names that match the regexp pattern;
|
479
|
+
- `String` - names which starts with a passed string;
|
480
|
+
- `:trim_prefix` (`false` by default);
|
481
|
+
|
482
|
+
```ruby
|
483
|
+
# some env variables
|
484
|
+
ENV['QONFIG_BOOLEAN'] = 'true'
|
485
|
+
ENV['QONFIG_INTEGER'] = '0'
|
486
|
+
ENV['QONFIG_STRING'] = 'none'
|
487
|
+
ENV['QONFIG_ARRAY'] = '1, 2.5, t, f, TEST'
|
488
|
+
ENV['QONFIG_MESSAGE'] = '"Hello, Qonfig!"'
|
489
|
+
ENV['RUN_CI'] = '1'
|
490
|
+
|
491
|
+
class Config < Qonfig::DataSet
|
492
|
+
# nested
|
493
|
+
setting :qonfig do
|
494
|
+
load_from_env convert_values: true, prefix: 'QONFIG' # or /\Aqonfig.*\z/i
|
495
|
+
end
|
496
|
+
|
497
|
+
setting :trimmed do
|
498
|
+
load_from_env convert_values: true, prefix: 'QONFIG_', trim_prefix: true # trim prefix
|
499
|
+
end
|
500
|
+
|
501
|
+
# on the root
|
502
|
+
load_from_env
|
503
|
+
end
|
504
|
+
|
505
|
+
config = Config.new
|
506
|
+
|
507
|
+
# customized
|
508
|
+
config.settings['qonfig']['QONFIG_BOOLEAN'] # => true ('true' => true)
|
509
|
+
config.settings['qonfig']['QONFIG_INTEGER'] # => 0 ('0' => 0)
|
510
|
+
config.settings['qonfig']['QONFIG_STRING'] # => 'none'
|
511
|
+
config.settings['qonfig']['QONFIG_ARRAY'] # => [1, 2.5, true, false, 'TEST']
|
512
|
+
config.settings['qonfig']['QONFIG_MESSAGE'] # => 'Hello, Qonfig!'
|
513
|
+
config.settings['qonfig']['RUN_CI'] # => Qonfig::UnknownSettingError
|
514
|
+
|
515
|
+
# trimmed (and customized)
|
516
|
+
config.settings['trimmed']['BOOLEAN'] # => true ('true' => true)
|
517
|
+
config.settings['trimmed']['INTEGER'] # => 0 ('0' => 0)
|
518
|
+
config.settings['trimmed']['STRING'] # => 'none'
|
519
|
+
config.settings['trimmed']['ARRAY'] # => [1, 2.5, true, false, 'TEST']
|
520
|
+
config.settings['trimmed']['MESSAGE'] # => 'Hello, Qonfig!'
|
521
|
+
config.settings['trimmed']['RUN_CI'] # => Qonfig::UnknownSettingError
|
522
|
+
|
523
|
+
# default
|
524
|
+
config.settings['QONFIG_BOOLEAN'] # => 'true'
|
525
|
+
config.settings['QONFIG_INTEGER'] # => '0'
|
526
|
+
config.settings['QONFIG_STRING'] # => 'none'
|
527
|
+
config.settings['QONFIG_ARRAY'] # => '1, 2.5, t, f, TEST'
|
528
|
+
config.settings['QONFIG_MESSAGE'] # => '"Hello, Qonfig!"'
|
529
|
+
config.settings['RUN_CI'] # => '1'
|
530
|
+
```
|
531
|
+
|
532
|
+
---
|
533
|
+
|
534
|
+
### Load from \_\_END\_\_
|
535
|
+
|
536
|
+
- aka `load_from_self`
|
537
|
+
|
538
|
+
```ruby
|
539
|
+
class Config < Qonfig::DataSet
|
540
|
+
load_from_self # on the root
|
541
|
+
|
542
|
+
setting :clowd do
|
543
|
+
load_from_self # nested
|
544
|
+
end
|
545
|
+
end
|
546
|
+
|
547
|
+
config = Config.new
|
548
|
+
|
549
|
+
# on the root
|
550
|
+
config.settings.ruby_version # => '2.5.1'
|
551
|
+
config.settings.secret_key # => 'top-mega-secret'
|
552
|
+
config.settings.api_host # => 'super.puper-google.com'
|
553
|
+
config.settings.connection_timeout.seconds # => 10
|
554
|
+
config.settings.connection_timeout.enabled # => false
|
555
|
+
|
556
|
+
# nested
|
557
|
+
config.settings.nested.ruby_version # => '2.5.1'
|
558
|
+
config.settings.nested.secret_key # => 'top-mega-secret'
|
559
|
+
config.settings.nested.api_host # => 'super.puper-google.com'
|
560
|
+
config.settings.nested.connection_timeout.seconds # => 10
|
561
|
+
config.settings.nested.connection_timeout.enabled # => false
|
562
|
+
|
563
|
+
__END__
|
564
|
+
|
565
|
+
ruby_version: <%= RUBY_VERSION %>
|
566
|
+
secret_key: top-mega-secret
|
567
|
+
api_host: super.puper-google.com
|
568
|
+
connection_timeout:
|
569
|
+
seconds: 10
|
570
|
+
enabled: false
|
571
|
+
```
|
572
|
+
|
573
|
+
---
|
574
|
+
|
575
|
+
### Smart Mixin
|
576
|
+
|
577
|
+
- class-level:
|
578
|
+
- `.configuration` - settings definitions;
|
579
|
+
- `.configure` - configuration;
|
580
|
+
- `.config` - config object;
|
581
|
+
- settings definitions are inheritable;
|
582
|
+
- instance-level:
|
583
|
+
- `#configure` - configuration;
|
584
|
+
- `#config` - config object;
|
585
|
+
|
586
|
+
```ruby
|
587
|
+
# --- usage ---
|
588
|
+
|
589
|
+
class Application
|
590
|
+
# make configurable
|
591
|
+
include Qonfig::Configurable
|
592
|
+
|
593
|
+
configuration do
|
594
|
+
setting :user
|
595
|
+
setting :password
|
596
|
+
end
|
597
|
+
end
|
598
|
+
|
599
|
+
app = Application.new
|
600
|
+
|
601
|
+
# class-level config
|
602
|
+
Application.config.settings.user # => nil
|
603
|
+
Application.config.settings.password # => nil
|
604
|
+
|
605
|
+
# instance-level config
|
606
|
+
app.config.settings.user # => nil
|
607
|
+
app.config.settings.password # => nil
|
608
|
+
|
609
|
+
# class-level configuration
|
610
|
+
Application.configure do |conf|
|
611
|
+
conf.user = '0exp'
|
612
|
+
conf.password = 'test123'
|
613
|
+
end
|
614
|
+
|
615
|
+
# instance-level configuration
|
616
|
+
app.configure do |conf|
|
617
|
+
conf.user = 'admin'
|
618
|
+
conf.password = '123test'
|
619
|
+
end
|
620
|
+
|
621
|
+
# class has own config object
|
622
|
+
Application.config.settings.user # => '0exp'
|
623
|
+
Application.config.settings.password # => 'test123'
|
624
|
+
|
625
|
+
# instance has own config object
|
626
|
+
app.config.settings.user # => 'admin'
|
627
|
+
app.config.settings.password # => '123test'
|
628
|
+
|
629
|
+
# and etc... (all Qonfig-related features)
|
630
|
+
```
|
631
|
+
|
632
|
+
```ruby
|
633
|
+
# --- inheritance ---
|
634
|
+
|
635
|
+
class BasicApplication
|
636
|
+
# make configurable
|
637
|
+
include Qonfig::Configurable
|
638
|
+
|
639
|
+
configuration do
|
640
|
+
setting :user
|
641
|
+
setting :pswd
|
642
|
+
end
|
643
|
+
|
644
|
+
configure do |conf|
|
645
|
+
conf.user = 'admin'
|
646
|
+
conf.pswd = 'admin'
|
647
|
+
end
|
648
|
+
end
|
649
|
+
|
650
|
+
class GeneralApplication < BasicApplication
|
651
|
+
# extend inherited definitions
|
652
|
+
configuration do
|
653
|
+
setting :db do
|
654
|
+
setting :adapter
|
655
|
+
end
|
656
|
+
end
|
657
|
+
|
658
|
+
configure do |conf|
|
659
|
+
conf.user = '0exp' # .user inherited from BasicApplication
|
660
|
+
conf.pswd = '123test' # .pswd inherited from BasicApplication
|
661
|
+
conf.db.adapter = 'pg'
|
662
|
+
end
|
663
|
+
end
|
664
|
+
|
665
|
+
BasicApplication.config.to_h
|
666
|
+
{ 'user' => 'admin', 'pswd' => 'admin' }
|
667
|
+
|
668
|
+
GeneralApplication.config.to_h
|
669
|
+
{ 'user' => '0exp', 'pswd' => '123test', 'db' => { 'adapter' => 'pg' } }
|
670
|
+
|
671
|
+
# and etc... (all Qonfig-related features)
|
672
|
+
```
|
673
|
+
|
674
|
+
---
|
675
|
+
|
676
|
+
## Contributing
|
677
|
+
|
678
|
+
- Fork it ( https://github.com/0exp/qonfig/fork )
|
679
|
+
- Create your feature branch (`git checkout -b feature/my-new-feature development`)
|
680
|
+
- Commit your changes (`git commit -am 'Add some feature'`)
|
681
|
+
- Push to the branch (`git push origin feature/my-new-feature`)
|
682
|
+
- Create new Pull Request
|
683
|
+
|
231
684
|
## License
|
232
685
|
|
233
686
|
Released under MIT License.
|
234
687
|
|
235
688
|
## Authors
|
236
689
|
|
237
|
-
Rustam Ibragimov.
|
690
|
+
[Rustam Ibragimov](https://github.com/0exp)
|