README.md in qonfig-0.17.0 vs README.md in qonfig-0.18.0
- old
+ new
@@ -42,16 +42,20 @@
- [Hash representation](#hash-representation)
- [Smart Mixin](#smart-mixin) (`Qonfig::Configurable`)
- [Instantiation without class definition](#instantiation-without-class-definition) (`Qonfig::DataSet.build(&definitions)`)
- [Interaction](#interaction)
- [Iteration over setting keys](#iteration-over-setting-keys) (`#each_setting`, `#deep_each_setting`)
+ - [List of config keys](#list-of-config-keys) (`#keys`, `#root_keys`)
- [Config reloading](#config-reloading) (reload config definitions and option values)
- [Clear options](#clear-options) (set to `nil`)
- [State freeze](#state-freeze)
- [Settings as Predicates](#settings-as-predicates)
- [Setting key existence](#setting-key-existence) (`#key?`/`#option?`/`#setting?`)
- - [Run arbitary code with temporary settings](#run-arbitary-code-with-temporary-settings) (`#with(configs = {}, &arbitary_code)`)
+ - [Run arbitrary code with temporary settings](#run-arbitrary-code-with-temporary-settings) (`#with(configs = {}, &arbitrary_code)`)
+- [Import settings / Export settings](#import-settings--export-settings)
+ - [Import config settings](#import-config-settings) (`as instance methods`)
+ - [Export config settings](#export-config-settings) (`as singleton methods`)
- [Validation](#validation)
- [Introduction](#introduction)
- [Key search pattern](#key-search-pattern)
- [Proc-based validation](#proc-based-validation)
- [Method-based validation](#method-based-validation)
@@ -73,11 +77,11 @@
- [Load setting values from file manually](#load-setting-values-from-file-manually-by-instance)
- **Daily work**
- [Save to JSON file](#save-to-json-file) (`#save_to_json`)
- [Save to YAML file](#save-to-yaml-file) (`#save_to_yaml`)
- [Plugins](#plugins)
- - [toml](#plugins-toml) (provides `load_from_toml`, `save_to_toml`, `expose_toml`)
+ - [toml](#plugins-toml) (support for `TOML` format)
- [Roadmap](#roadmap)
---
## Definition
@@ -491,10 +495,12 @@
---
### Instantiation without class definition
+- without inheritance:
+
```ruby
config = Qonfig::DataSet.build do
setting :user, 'D@iVeR'
setting :password, 'test123'
@@ -508,21 +514,39 @@
config.settings.user # => 'D@iVeR'
config.settings.password # => 'test123'
config.custom_method # => 'custom_result'
```
+- with inheritance:
+
+```ruby
+class GeneralConfig < Qonfig::DataSet
+ setting :db_adapter, :postgresql
+end
+
+config = Qonfig::DataSet.build(GeneralConfig) do
+ setting :web_api, 'api.google.com'
+end
+
+config.is_a?(Qonfig::DataSet) # => true
+
+config.settings.db_adapter # => :postgresql
+config.settings.web_api # => "api.google.com"
+```
+
---
## Interaction
- [Iteration over setting keys](#iteration-over-setting-keys) (`#each_setting`, `#deep_each_setting`)
+- [List of config keys](#list-of-config-keys) (`#keys`, `#root_keys`)
- [Config reloading](#config-reloading) (reload config definitions and option values)
-- [Clear options](#clear-options) (set to nil)
+- [Clear options](#clear-options) (set to `nil`)
- [State freeze](#state-freeze)
- [Settings as Predicates](#settings-as-predicates)
- [Setting key existence](#setting-key-existence) (`#key?`/`#option?`/`#setting?`)
-- [Run arbitary code with temporary settings](#run-arbitary-code-with-temporary-settings)
+- [Run arbitrary code with temporary settings](#run-arbitrary-code-with-temporary-settings)
---
### Iteration over setting keys
@@ -574,12 +598,100 @@
{ 'telegraf_prefix' => 'test' }
```
---
+### List of config keys
+
+- `#keys` - returns a list of all config keys in dot-notation format;
+ - `all_variants:` - get all possible variants of the config's keys sequences (`false` by default);
+ - `only_root:` - get only the root config keys (`false` by default);
+- `#root_keys` - returns a list of root config keys (an alias for `#keys(only_root: true)`);
+
+```ruby
+# NOTE: suppose we have the following config
+
+class Config < Qonfig::DataSet
+ setting :credentials do
+ setting :social do
+ setting :service, 'instagram'
+ setting :login, '0exp'
+ end
+
+ setting :admin do
+ setting :enabled, true
+ end
+ end
+
+ setting :server do
+ setting :type, 'cloud'
+ setting :options do
+ setting :os, 'CentOS'
+ end
+ end
+end
+
+config = Config.new
+```
+
+#### Default behavior
+
+```ruby
+config.keys
+
+# the result:
+[
+ "credentials.social.service",
+ "credentials.social.login",
+ "credentials.admin.enabled",
+ "server.type",
+ "server.options.os"
+]
+```
+
+#### All key variants
+
+```ruby
+config.keys(all_variants: true)
+
+# the result:
+[
+ "credentials",
+ "credentials.social",
+ "credentials.social.service",
+ "credentials.social.login",
+ "credentials.admin",
+ "credentials.admin.enabled",
+ "server",
+ "server.type",
+ "server.options",
+ "server.options.os"
+]
+```
+
+#### Only root keys
+
+```ruby
+config.keys(only_root: true)
+
+# the result:
+['credentials', 'server']
+```
+
+```ruby
+config.root_keys
+
+# the result:
+['credentials', 'server']
+```
+
+---
+
### Config reloading
+- method signature: `#reload!(configurations = {}, &configuration)`;
+
```ruby
class Config < Qonfig::DataSet
setting :db do
setting :adapter, 'postgresql'
end
@@ -622,10 +734,13 @@
---
### Clear options
+- set all config's settings to `nil`;
+- method signature: `#clear!`;
+
```ruby
class Config
setting :database do
setting :user
setting :password
@@ -657,10 +772,12 @@
---
### State freeze
+- method signature: `#freeze!`;
+
```ruby
class Config < Qonfig::DataSet
setting :logger, Logger.new(STDOUT)
setting :worker, :sidekiq
setting :db do
@@ -754,14 +871,14 @@
config.option?(:credentials, :password) # => true
```
---
-### Run arbitary code with temporary settings
+### Run arbitrary code with temporary settings
-- provides a way to run an arbitary code with temporarily specified settings;
-- your arbitary code can temporary change any setting too - all settings will be returned to the original state;
+- provides a way to run an arbitrary code with temporarily specified settings;
+- your arbitrary code can temporary change any setting too - all settings will be returned to the original state;
- (it is convenient to run code samples by this way in tests (with substitued configs));
- it is fully thread-safe `:)`;
```ruby
class Config < Qonfig::DataSet
@@ -789,10 +906,192 @@
config.settings.queue.options # => {}
```
---
+## Import settings / Export settings
+
+- [Import config settings](#import-config-settings) (`as instance methods`)
+- [Export config settings](#export-config-settings) (`as singleton methods`)
+
+Sometimes the nesting of configs in your project is quite high, and it makes you write the rather "cumbersome" code
+(`config.settings.web_api.credentials.account.auth_token` for example). Frequent access to configs in this way is inconvinient - so developers wraps
+such code by methods or variables. In order to make developer's life easer `Qonfig` provides a special Import API simplifies the config importing
+(gives you `.import_settings` DSL) and gives an ability to instant config setting export from a config object (gives you `#export_settings` config's method).
+
+---
+
+### Import config settings
+
+- `Qonfig::Imports` - a special mixin that provides the convenient DSL to work with config import features (`.import_settings` method);
+- `.import_settings` - DSL method for importing configuration settings (from a config instance) as instance methods of a class;
+- (**IMPORTANT**) `import_settings` imports config settings as access methods to config's settings (creates `attr_reader`s for your config);
+- signature: `.import_settings(config_object, *setting_keys, mappings: {}, prefix: '', raw: false)`
+ - `config_object` - an instance of `Qonfig::DataSet` whose config settings should be imported;
+ - `*setting_keys` - an array of dot-notaed config's setting keys that should be imported
+ (dot-notaed key is a key that describes each part of nested setting key as a string separated by `dot`-symbol);
+ - last part of dot-notated key will become a name of the setting access instance method;
+ - `mappings:` - a map of keys that describes custom method names for each imported setting;
+ - `prefix:` - prexifies setting access method name with custom prefix;
+ - `raw:` - use nested settings as objects or hashify them (`false` by default (means "hashify nested settings"));
+
+---
+
+Suppose we have a config with deeply nested keys:
+
+```ruby
+# NOTE: (Qonfig::DataSet.build creates a class and instantly instantiates it)
+AppConfig = Qonfig::DataSet.build do
+ setting :web_api do
+ setting :credentials do
+ setting :account do
+ setting :login, 'DaiveR'
+ setting :auth_token, 'IAdkoa0@()1239uA'
+ end
+ end
+ end
+end
+```
+
+Let's see what we can to do :)
+
+#### Import a set of setting keys (simple dot-noated key list)
+
+- last part of dot-notated key will become a name of the setting access instance method;
+
+```ruby
+class ServiceObject
+ include Qonfig::Imports
+
+ import_settings(AppConfig,
+ 'web_api.credentials.account.login',
+ 'web_api.credentials.account'
+ )
+end
+
+service = ServiceObject.new
+
+service.login # => "D@iVeR"
+service.account # => { "login" => "D@iVeR", "auth_token" => IAdkoa0@()1239uA" }
+```
+
+#### Import with custom method names (mappings)
+
+- `mappings:` defines a map of keys that describes custom method names for each imported setting;
+
+```ruby
+class ServiceObject
+ include Qonfig::Imports
+
+ import_settings(AppConfig, mappings: {
+ account_data: 'web_api.credentials.account', # NOTE: name access method with "account_data"
+ secret_token: 'web_api.credentials.account.auth_token' # NOTE: name access method with "secret_token"
+ })
+end
+
+service = ServiceObject.new
+
+service.account_data # => { "login" => "D@iVeR", "auth_token" => "IAdkoa0@()1239uA" }
+service.auth_token # => "IAdkoa0@()1239uA"
+```
+
+#### Prexify method name
+
+- `prefix:` - prexifies setting access method name with custom prefix;
+
+```ruby
+class ServiceObject
+ include Qonfig::Imports
+
+ import_settings(AppConfig,
+ 'web_api.credentials.account',
+ mappings: { secret_token: 'web_api.credentials.account.auth_token' },
+ prefix: 'config_'
+ )
+end
+
+service = ServiceObject.new
+
+service.config_credentials # => { login" => "D@iVeR", "auth_token" => "IAdkoa0@()1239uA" }
+service.config_secret_token # => "IAdkoa0@()1239uA"
+```
+
+#### Import nested settings as raw Qonfig::Settings objects
+
+- `raw: false` is used by default (hashify nested settings)
+
+```ruby
+# NOTE: import nested settings as raw objects (raw: true)
+class ServiceObject
+ include Qonfig::Imports
+
+ import_settings(AppConfig, 'web_api.credentials', raw: true)
+end
+
+service = ServiceObject.new
+
+service.credentials # => <Qonfig::Settings:0x00007ff8>
+service.credentials.account.login # => "D@iVeR"
+service.credentials.account.auth_token # => "IAdkoa0@()1239uA"
+```
+
+```ruby
+# NOTE: import nested settings as converted-to-hash objects (raw: false) (default behavior)
+class ServiceObject
+ include Qonfig::Imports
+
+ import_settings(AppConfig, 'web_api.credentials', raw: false)
+end
+
+service = ServiceObject.new
+
+service.credentials # => { "account" => { "login" => "D@iVeR", "auth_token" => "IAdkoa0@()1239uA"} }
+```
+
+---
+
+### Export config settings
+
+- all config objects can export their settings to an arbitrary object as singleton methods;
+- (**IMPORTANT**) `export_settings` exports config settings as access methods to config's settings (creates `attr_reader`s for your config);
+- signature: `#export(exportable_object, *setting_keys, mappings: {}, prefix: '', raw: false)`:
+ - `exportable_object` - an arbitrary object for exporting;
+ - `*setting_keys` - an array of dot-notaed config's setting keys that should be exported
+ (dot-notaed key is a key that describes each part of nested setting key as a string separated by `dot`-symbol);
+ - last part of dot-notated key will become a name of the setting access instance method;
+ - `mappings:` - a map of keys that describes custom method names for each exported setting;
+ - `prefix:` - prexifies setting access method name with custom prefix;
+ - `raw:` - use nested settings as objects or hashify them (`false` by default (means "hashify nested settings"));
+- works in `.import_settings` manner [doc](#import-config-settings) (see examples and documentation above `:)`)
+
+```ruby
+class Config < Qonfig::DataSet
+ setting :web_api do
+ setting :credentials do
+ setting :account do
+ setting :login, 'DaiveR'
+ setting :auth_token, 'IAdkoa0@()1239uA'
+ end
+ end
+ end
+end
+
+class ServiceObject; end
+
+config = Config.new
+service = ServiceObject.new
+
+service.config_account # => NoMethodError
+
+# NOTE: export settings as access methods to config's settings
+config.export(service, 'web_api.credentials.account', prefix: 'config_')
+
+service.account # => { "login" => "D@iVeR", "auth_token" => "IAdkoa0@()1239uA" }
+```
+
+---
+
## Validation
- [Introduction](#introduction)
- [Key Search Pattern](#key-search-pattern)
- [Proc-based validation](#proc-based-validation)
@@ -1733,23 +2032,23 @@
```
#### File does not exist
```ruby
-# strict behavior (default)
+# non-strict behavior (default)
class Config < Qonfig::DataSet
values_file 'sidekiq.yml'
end
-config = Config.new # => Qonfig::FileNotFoundError
+config = Config.new # no error
-# non-strict behavior (strict: false)
+# strict behavior (strict: true)
class Config < Qonfig::DataSet
- values_file 'sidekiq.yml', strict: false
+ values_file 'sidekiq.yml', strict: true
end
-config = Config.new # no error
+config = Config.new # => Qonfig::FileNotFoundError
```
---
### Load setting values from YAML file (by instance)
@@ -2199,10 +2498,12 @@
port: 12345
enabled: true
dynamic: 10
```
+---
+
### Plugins
```ruby
# --- show names of registered plugins ---
Qonfig.plugins # => array of strings
@@ -2248,11 +2549,9 @@
- support for persistent data storages (we want to store configs in multiple databases and files);
- Rails reload plugin;
- **Minor**:
- custom global (and class-level) validators (with a special Validator Definition DSL);
- support for "dot notation" in `#key?`, `#option?`, `#setting?`, `#dig`, `#subset`, `#slice`, `#slice_value`;
- - "load setting values from a file" (at instance level);
- - config improts (and exports);
- pretty print :)));
## Contributing
- Fork it ( https://github.com/0exp/qonfig/fork )