Extends YAML to support file based inheritance.
That can be very handy to build a configuration hierachy.
Add this line to your application's Gemfile:
gem 'yaml_extend'
And then execute:
$ bundle install
Or install it yourself as:
$ gem install yaml_extend
It is possible to build inheritance trees like:
defaults.yml
________\_________
\ \ \
dev.yml int.yml prod.yml
or like this:
default.yml english.yml default.yml german.yml
\ / \ /
uk.yml de.yml
|
at.yml
A file can inherit from as many as you want. Trees can be nested as deep as you want.
YAML files are deep merged. Two methods are supported:
- :breadthfirst: the latest specified child file overwrites the former ones, uses deep_merge
- :postorder : the tree is traversed in a postorder fashion, where the newer node gets merged into the existing merge, uses deep_merge! Array values are merged as well by default. You can specifiy this with the 3rd Parameter.
The files to inherit from are specified by the key 'extends:' in the YAML file. That key can be customized if you prefer another one. See the examples below.
yaml_extend adds the method YAML#ext_load_file to YAML.
This method works like the original YAML#load_file, by extending it with file inheritance.
Given the following both files are defined:
# start.yml
extends: 'super.yml'
data:
name: 'Mr. Superman'
age: 134
favorites:
- 'Raspberrys'
# super.yml
data:
name: 'Unknown'
power: 2000
favorites:
- 'Bananas'
- 'Apples'
When you then call #ext_load_file
config = YAML.ext_load_file 'start.yml'
the returned YAML value results in
data:
name: 'Mr. Superman'
age: 134
power: 2000
favorites:
- 'Bananas'
- 'Apples'
- 'Raspberrys'
If you want to inherit from several files, you can specify a list (Array) of files. They are merged from top to bottom, so the latest file "wins" - that means it overwrites duplicate values if they exist with the values in the latest file where they occur.
extends:
- 'super_file.yml'
- 'parent_file.yml'
...
If you don't want to use the default key 'extends:', you can specify your own custom key in two ways.
#custom1.yml
inherit_from:
- 'super_file.yml'
foo: 'bar'
...
You can specify the key by parameter, this is the way to go if you want to use the different key only once or you use the #ext_load_file method only once in your application.
config = YAML.ext_load_file 'custom1.yml', 'inherit_from'
You can specify the key by configuration globally. So you only need to set the key once and not as parameter anymore
YAML.ext_load_key = 'inherit_from'
config = YAML.ext_load_file 'custom1.yml'
To reset the global inheritance key, you can either set it to nil or call the #reset_load_key method.
YAML.reset_load_key # more readable
YAML.ext_load_key = nil # more explicit
#custom2.yml
options:
extend_file: 'super_file.yml'
database: false
foo: 'bar'
...
config = YAML.ext_load_file 'custom2.yml', ['options','extend_file']
YAML#ext_load_file(yaml_path, inheritance_key='extends', extend_existing_arrays=true, config = {}, files: [], tree_traversal: :breadthfirst))
- yaml_path relative or absolute path to yaml file to inherit from
- inheritance_key you can overwrite the default key, if you use the default 'extends' already as part of your configuration. The inheritance_key is NOT included, that means it will be deleted, in the final merged file. Default: 'extends'
- extend_existing_arrays Extends existing arrays in yaml structure instead of replacing them. Default: true
- config only intended to be used by the method itself due recursive algorithm
- files encountered files will be appended to this list
- tree_traversal :breadthfirst or :postorder. Default: :breadthfirst
Bug reports and pull requests are welcome on GitHub at https://github.com/magynhard/yaml_extend. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.