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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d774926f0d94544e9d256b7c3e06bbc51b16a51a1323fbcb1f020a1c377ffaf7
4
- data.tar.gz: a3d2769d42ba24938db56bd853f65b041a7053af462644a6d4e3ac3109c3b121
3
+ metadata.gz: 364dfdc09c159ed886729491cc0d066f961b5be382b766d99d57705fca5f88d7
4
+ data.tar.gz: 9525458cf3d84fa9588ab48805cdb8a5ec0150278a7658986fb6325efcd2d191
5
5
  SHA512:
6
- metadata.gz: 82ac7dd98fdccf5ab5ba846a9c733fbb8e3523676a23b390aca49c587e01b1cf9c76602d5909cda2736c7e4d572ffe219b85e3f7267f4499051c579a5bf59997
7
- data.tar.gz: 747f86b8b8f8f2a348ae906e0e3e75a37f45afd896874ee1eb56aa7b66ee6a4c4581d48fbbe3d7d203879c345ff0894ca780f12a5bcbd660b421f7e202c29028
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: 17
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.1.0] - 2018-05-xx
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 &middot; [![Gem Version](https://badge.fury.io/rb/qonfig.svg)](https://badge.fury.io/rb/qonfig) [![Build Status](https://travis-ci.org/0exp/qonfig.svg?branch=master)](https://travis-ci.org/0exp/qonfig) [![Coverage Status](https://coveralls.io/repos/github/0exp/qonfig/badge.svg)](https://coveralls.io/github/0exp/qonfig)
1
+ # Qonfig &middot; [![Gem Version](https://badge.fury.io/rb/qonfig.svg)](https://badge.fury.io/rb/qonfig) [![Build Status](https://travis-ci.org/0exp/qonfig.svg?branch=master)](https://travis-ci.org/0exp/qonfig) [![Coverage Status](https://coveralls.io/repos/github/0exp/qonfig/badge.svg?branch=master)](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 # => 'api.service.com'
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] # => 'api.service.com'
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 block
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: :memory_sync
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: { engine: :ok },
205
- hash: { engine: :native },
229
+ "serializers": {
230
+ "json" => { "engine" => :ok },
231
+ "hash" => { "engine" => :native },
206
232
  },
207
- adapter: { default: :memory_sync },
208
- logger: #<Logger:0x4b0d79fc>
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)