Module: Jac::Configuration
- Defined in:
- lib/jac/configuration.rb,
lib/jac/merger.rb
Overview
Configuration is loaded from well formed YAML streams. Each document expected to be key-value mapping where keys a profile names and values is a profile content. Profile itself is key-value mapping too. Except reserved key names (i.e. extends) each key in profile is a configuration field. For example following yaml document
“‘
foo:
bar: 42
qoo:
bar: 32
“‘
represents description of two profiles, foo and qoo, where field bar is set to 42 and 32 respectively.
Profile can be constructed using combination of other profiles for example having debug and release profiles for testing and production. And having remote and local profiles for building on local or remote machine. We cant get ‘debug,local`, `debug,remote`, `release,local` and `release,remote` profiles. Each of such profiles is a result of merging values of listed profiles. When merging profile with another configuration resolver overwrites existing fields. For example if debug and local for some reason have same field. In profile `debug,local` value from debug profile will be overwritten with value from local profile.
## Extending profiles
One profile can extend another. Or any amount of other profiles. To specify this one should use extends field like that
“‘
base:
application_name: my-awesome-app
port: 80
version:
version_name: 0.0.0
version_code: 42
debug:
extends: [base, version]
port: 9292
“‘
In this example debug will receive following fields:
“‘ application_name: my-awesome-app # from base profile port: 9292 # from debug profile version_name: 0.0.0 # from version profile version_code: 42 # from version profile “`
## Merging multiple configuration files
Configuration can be loaded from multiple YAML documents. Before resolve requested profile all described profiles are merged down together. Having sequence of files like .application.yml, .application.user.yml with following content
“‘ # .application.yml base:
user: deployer
debug:
extends: base
# ... other values
“‘
“‘ # .application.user.yml base:
user: developer
“‘
We’ll get user field overwritten with value from .application.user.yml. And only after that construction of resulting profile will begin (for example debug)
## String evaluation
Configuration resolver comes with powerful yet dangerous feature: it allows evaluate strings as ruby expressions like this:
“‘ foo:
build_time: "#{Time.now}" # Will be evaluated at configuration resolving step
“‘
Configuration values are available to and can be referenced with c:
“‘ base:
application_name: my-awesome-app
debug:
extends: base
server_name: "#{c.application_name}-debug" # yields to my-awesome-app-debug
release:
extends: base
server_name: "#{c.application_name}-release" # yields to my-awesome-app-release
“‘
All strings evaluated after profile is constructed thus you don’t need to have declared values in current profile but be ready to get nil.
## Merging values
By default if one value definition overwrites another ### Merging hashes
### Merging sets
## Generic profiles
Same result as shown above can be achieved with generic profiles. Generic profile is a profile which name is regex (i.e. contained in /.../):
“‘ base:
application_name: my-awesome-app
/(release|debug)/: # Profile name is a regex, with single capture (1)
extends: base
server_name: "#{c.application_name}-#{c.captures[1]}" # yields my-awesome-app-release or my-awesome-app-debug
“‘
If profile name matches multiple generic profiles it not defined which profile will be used.
Defined Under Namespace
Classes: ConfigurationEvaluator, ConfigurationReader, EvaluationContext, Merger, ProfileResolver
Constant Summary collapse
- CONFIGURATION_FILES =
List of files where configuration can be placed
-
application.yml- expected to be main configuration file.
Usually it placed under version control.
-
application.user.yml- user defined overrides for main
configuration, sensitive data which can’t be placed under version control.
-
application.override.yml- final overrides.
-
%w[application.yml application.user.yml application.override.yml].freeze
Class Method Summary collapse
-
.load(profile, files: CONFIGURATION_FILES, dir: Dir.pwd) ⇒ Object
Read configuration from configuration files.
-
.read(profile, *streams) ⇒ OpenStruct
Generates configuration object for given profile and list of streams with YAML document names to read.
Class Method Details
.load(profile, files: CONFIGURATION_FILES, dir: Dir.pwd) ⇒ Object
Read configuration from configuration files.
397 398 399 400 401 402 403 404 |
# File 'lib/jac/configuration.rb', line 397 def load(profile, files: CONFIGURATION_FILES, dir: Dir.pwd) # Read all known files streams = files .map { |f| [File.join(dir, f), f] } .select { |path, _name| File.exist?(path) } .map { |path, name| [IO.read(path), name] } read(profile, *streams) end |
.read(profile, *streams) ⇒ OpenStruct
Generates configuration object for given profile and list of streams with YAML document names to read
391 392 393 394 |
# File 'lib/jac/configuration.rb', line 391 def read(profile, *streams) profile = [ConfigurationReader::DEFAULT_PROFILE_NAME] if profile.empty? ConfigurationReader.new(streams).read(*profile) end |