All notable changes to this project will be documented in this file.
- Support for
truffleruby;
- Performance: nested / dot-notated reads (
config['a.b.c.d.e.f'],config.dig(...)) are now memoized inside each config instance instead of re-splitting and re-digging the key on every access. The cache is dropped on any mutation and the invalidation cascades up through all parent config instances ("matryoshka" cache invalidation), so nested configs (which are separate instances) never serve stale values.
- Updated development dependencies;
- Updated code style;
- Dropped EOL rubies support. Now Qonfig supports rubies started from
>= 3.1; - CI: returned separated plugin-related specs (
bin/rspec -w+bin/rspec -n(with- and without- plugins respectively)); - CI: dropped coveralls (temporary);
- CI: droppet java-based rubies support (temporary);
- Simplified CI (temporary);
replace_on_mergeoption for load_from, expose-like methods that allows to configure behaviour on the conflicting key: deep merge (by default) or replacing.
- Support for the new
toml-rbrelease (2.1); - Updated dev-dependencies;
- Existing code base was adopted to the new rubocop ruleset;
- Drop Ruby 2.5 support.
- Fix YAML loading in Psych v4 (#132).
- Support
ERBinload_from_jsonmethod;
- Support for Vault config provider:
- realized as a plugin (
Qonfig.plugin(:vault)); - provides
#load_from_vault,#expose_vaultmethods and works in#*_yaml-like manner); - depends on
gem vault (>= 0.1)
- realized as a plugin (
Qonfig::Settings#[]behave likeQonfig::Settings#__dig__;- An ability to represent the config hash in dot-notated style (all config keys are represented in dot-notated format):
- works via
#to_h(dot_style: true); key_transformer:andvalue_transfomer:options are supported too;
- works via
class Config << Qonfig::DataSet
setting :database do
setting :host, 'localhost'
setting :port, 6432
end
setting :api do
setting :rest_enabled, true
setting :rpc_enabled, false
end
end
Config.new.to_h(dot_style: true)
# =>
{
'database.host' => 'localhost',
'database.port' => 6432,
'api.rest_enabled' => true,
'api.rpc_enabled' => false,
}- Enhanced dot-notated key resolving algorithm: now it goes through the all dot-notated key parts
until it finds the required setting key (or fails with
Qonfig::UnknowSettingKeyError);
- (Pretty-Print Plugin):
- dot-noted setting keys can not be pretty-printed (they raise
Qonfig::UnknownSettingKeyError); - added
setandppas preloaded dependencies;
- dot-noted setting keys can not be pretty-printed (they raise
- Support for Ruby@2.7;
- Support for
Pathnamefile path in.load_from_json,.load_from_yaml,.load_from_toml,.expose_yaml,.expose_json,.expose_toml;
- Support for
Pathnamefile path in.values_file,#load_from_file,#load_from_yaml,#load_from_jsonand#load_from_toml;
- Brand new type of config objects
Qonfig::Compacted:- represents the compacted config object with setting readers and setting writers only;
- setting keys are represented as direct instace methods (
#settingsinvokation does not need); - no any other useful instance-based functionality;
- full support of
Qonfig::DataSetDSL commands (.setting,.validate,.add_validator,.load_from_x/.expose_xand etc); - can be instantiated by:
- by existing config object:
Qonfig::DataSet#compactedorQonfig::Compacted.build_from(config, &configuration) - by direct instantiation:
Qonfig::Compacted.new(settings_values = {}, &configuration); - by implicit instance building without explicit class definition
Qonfig::Compacted.build(&dsl_commands) # => instance of Qonfig::Compacted;
- by existing config object:
- Added
Qonfig::DataSet.build_compactedmethod: works inQonfig::DataSet.buildmanner but returns compacted config object (Qonfig::Compacted); - Added missing
#[]=(key, value)accessor-method forQonfig::DataSetobjects; - Added support for
do |config|configuration block in#load_from_self/#load_from_yaml/#load_from_json/#load_from_tomlvalues-loading methods; - Plugins
pretty_print:- added missing beautification logic for
Qonfig::Settingsobjects; - added support for
Qonfig::Compactedbeautification;
- added missing beautification logic for
#valid_with?now supports configuration block (do |config|);Import API: support for predicate methods;
.load_from_self: default format was changed from:yamlto:dynamic;.expose_self: default format was changed from:yamlto:dynamic;- Minor
Qonfig::DataSetandQonfig::Settings::Builderrefactorings;
- Configs without any setting key can not be imported and exported by generic key patterns (
*and#);
- Extended Validation API: you can define your own predefined validators via
.define_validator(name, &validation)directive; re_setting- a special DSL command method that fully redefines existing settings (redefines existing settings instead of reopening them);
- Support for Ruby 2.3 has ended.
- Invalid default values for
#export_settingsmethod attributes (invalidmappings:value);
- FINALY: support for dot-notation in
#key?,#option?,#setting?,#dig,#subset,#slice,#slice_value,[]; freeze_state!DSL directive (all your configs becomes frozen after being instantiated immediately);- Global
Qonfig::FrozenErrorerror forfrozen-based exceptions; - explicit validation of potential setting values:
#valid_with?(configurations = {})- check that current config instalce will be valid with passed configurations;.valid_with?(configurations = {})- check that potential config instancess will be valid with passed configurations;
#pretty_printplugin :) (Qonfig.plugin(:pretty_print));Qonfig.loaded_plugins/Qonfig.enabled_plugins- show loaded plugins;
Qonfig::FrozenSettingsErrornow inheritsQonfig::FrozenErrortype;
- New
yield_all:attribute for#deep_each_settingmethod (#deep_each_setting(yield_all: false, &block)))yield_all:means "yield all config objects" (end values and root setting objects those have nested settings) (falseby default)
#keys(all_variants: true)returns incorrect set of keys when some of keys has name in dot-notated format;
#keys- returns a list of all config keys in dot-notation format;#root_keys- returns a list of root config keys;- Inroduce
Import API:.import_settings- DSL method for importing configuration settings (from a config instance) as instance methods of a class;#export_settings- config's instance method that exports config settings to an arbitrary object as singelton methods;
- Introduce
strictvalidations:strict: falseoption ignoresnilvalues and used by default; - Setting's key existence check methods:
#key?(*key_path),#setting?(*key_path),#option?(*key_path); #with(temporary_configurations = {}, &arbitary_code)- run arbitary code with temporary settings;TOMLplugin: support for TOML version 0.5.0;- Introduce instance-level file loading methods that specifies a file with setting values for your defined settings:
.values_file- define a file that will be used during instantiation process;#load_from_file,#load_from_self,#load_from_yaml,#load_from_json,#load_from_toml(toml plugin) - instance methods for loading setting values on your config instance directly from a file;
Qonfig::DataSet.buildnow supports a Qonfig::DataSet-class attribute that should be inherited (selfis used by default):- new signature:
Qonfig::DataSet.build(base_config_klass = self, &config_class_definitions);
- new signature:
- Refacored DSL commands: introduce
Qonfig::Commands::Definitioncommands andQonfig::Commands::Instantiationcommands; - Updated runtime (
toml-rb1->2) and development dependencies;
Qonfig::DataSet.build(&config_klass_definitions)- build config instance immidietly withoutQonfig::DataSet-class definition;#subset- get a subset of config settings represented as a hash;
:format-option forload_from_selfandexpose_selfcommands that identifies which data format should be chosen for parsing;
expose_json- a command that provides an ability to define config settings by loading them from a json file where the concrete settings depends on the chosen environment;
- works in
expose_yamlmanner;
expose_self- a command that provides an ability to define config settings by loading them from the current file
where
__END__instruction is defined (concrete settings dependes on the chosen environment); - works with
YAMLformat;
- a command that provides an ability to define config settings by loading them from the current file
where
Qonfig::Settings::Callbacksis thread safe now;- Minor refactorings;
- Iteration over setting keys (
#each_setting { |key, value| },#deep_each_setting { |key, value| }); - Brand new
Validation API;
- Actualized development dependencies;
- Support for TOML (
.toml) format- realized as a plugin (
Qonfig.plugin(:toml)); - provides
#save_to_toml,#load_from_toml,#expose_tomlmethods and works in#*_yaml-like manner); - depends on
gem toml-rb (>= 1)
- realized as a plugin (
- Custom
bin/rspeccommand:bin/rspec -n- run tests without plugin tests;bin/rspec -w- run all tests;
- Added more convinient aliases for
Qonfig::DataSetinstances:#save_to_yaml=>#dump_to_yaml;#save_to_json=>#dump_to_json;#save_to_toml=>#dump_to_toml;
- Actualized development dependencies;
#save_to_json- save configurations to a json file (uses native::JSON.generateunder the hood);#save_to_yaml- save configurations to a yaml file (uses native::Psych.dumpunder the hood);
- new
#to_hsignature:#to_h(key_transformer:, value_transformer:):key_transformer- proc object used for key pre-processing (-> (key) { key }by default);:value_transformer- proc object used for value pre-processing (-> (value) { value }by default);
#slice_value- get a slice of config options as a hash set and fetch the required value using the given key set;
#slice- get a slice of config options as a hash set (works in a#digmanner);
expose_yaml,load_from_yaml,load_from_jsonandload_from_selftreats empty hash ({}) as an option with empty hash value (previously treated as a nested setting without options);
expose_yaml- a command that provides an ability to define config settings by loading them from a yaml file where the concrete settings depends on the chosen environment;
#shared_config- instance method that provides an access to the class level config object fromQonfig::Configurableinstances;
load_from_json- a command that provides an ability to define config settings by loading them from a json file (inload_from_yamlmanner);
- Support for Ruby 2.2 has ended;
- Introduce Plugin Ecosystem (
Qonfig::Plugins):- load plugin:
Qonfig.plugin('plugin_name')orQonfig.plugin(:plugin_name); - get registered plugins:
Qonfig.plugins #=> array of strings
- load plugin:
- Improved configuration process:
#configurecan take a hash as a configuration[option key => option]map of values;
#clear!causesQonfig::FrozenSettingsErrorif config object is frozen;
- Instant configuration via block
config = Config.new { |conf| <<your configuration code>> }; .load_from_envcommand - an ability to define config settings by loading them from ENV variable;.load_from_yamlcommand - an ability to define config settings by loading them from a yaml file;.load_from_selfcommand - an ability to load config definitions form the YAML instructions written in the file where the config class is defined (__END__section);#reload!- an ability to reload config isntance after any config class changes and updates;#clear!- an ability to set all options tonil;#dig- an ability to fetch setting values inHash#digmanner (fails withQonfig::UnknownSettingErrorwhen the required key does not exist);- Settings as Predicates - an ability to check the boolean nature of the config setting by appending
the question mark symbol (
?) at the end of setting name:nilandfalsesetting values indicatesfalse;- other setting values indicates
true; - setting roots always returns
true; - examples:
config.settings.database.user # => nil;config.settings.database.user? # => false;config.settings.database.host # => 'google.com';config.settings.database.host? # => true;config.settings.database? # => true (setting with nested option (setting root))
- Support for ERB instructions in YAML;
- Support for
HashWithIndifferentAccess-like behaviour; Qonfig::Settingsinstance method redefinition protection: the setting key can not have a name that matches an any instance method name ofQonfig::Settings;- Added
Qonfig::Configurablemixin - configuration behaviour for any classes and modules and their instances:- all
Qonfig-related features; - different class-level and instance-level config objects;
- working class-level inheritance :);
- all
- Full thread-safe implementation;
- Superclass of
Qonfig::FrozenSettingsError(it wasQonfig::Errorbefore):ruby >= 2.5- inherited from::FrozenError;ruby < 2.5- inherited from::RuntimeError;
.settingwill raise exceptions immediately:.setting(key, ...) { ... }- if setting key has incompatible type;.compose(config_class)- if composed config class is not a subtype ofQonfig::DataSet;
- Recoursive hash representation with deep nested
Qonfig::Settingsvalues (infinite loop); - Fixed re-assignment of the options with nested options (losing the nested options
due to the instance configuration). Now it causes
Qonfig::AmbigousSettingValueError.
- Release :)