Reputation: 64363
Is there a custom tag in YAML for ruby to include a YAML file inside a YAML file?
#E.g.:
--- !include
filename: another.yml
A similar question was asked some time ago and there was no relevant answer.
I am wondering if there is some custom tag for Ruby similar to this one for Python.
Upvotes: 21
Views: 20717
Reputation: 41
If you just want to inherit from another YAML file, there is a gem providing this functionality you are asking for by extending the ruby YAML library:
https://github.com/entwanderer/yaml_extend
https://rubygems.org/gems/yaml_extend
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.
# start.yml
extends: 'super.yml'
data:
name: 'Mr. Superman'
age: 134
favorites:
- 'Raspberrys'
-
# super.yml
data:
name: 'Unknown'
power: 2000
favorites:
- 'Bananas'
- 'Apples'
YAML.ext_load_file('start.yml')
results in
data:
name: 'Mr. Superman'
age: 134
power: 2000
favorites:
- 'Bananas'
- 'Apples'
- 'Raspberrys'
Upvotes: 4
Reputation: 191
If you are in Rails, YAML can include ERB.
Combine that together, and here is how you can use <%= %>
to include one file from another:
database.yml
<% if File.exists?('/tmp/mysql.sock') %>
<%= IO.read('config/database.mysql.yml') %>
<% else %>
<%= IO.read('config/database.sqlite.yml') %>
<% end %>
database.sqlite.yml
sqlite: &defaults
adapter: sqlite3
pool: 5
timeout: 5000
development:
<<: *defaults
database: db/development.sqlite3
test:
<<: *defaults
database: db/test.sqlite3
production:
<<: *defaults
database: db/production.sqlite3
database.mysql.yml
development:
adapter: mysql2
# ... the rest of your mysql configuration ...
Upvotes: 19
Reputation: 3001
!include
is not a directive but a tag.it is not a feature of Python (or PyYAML) but a feature of the "poze" library:
poze.configuration exposes a default directive named include.
YAML specification does not define such a standard tag.
Upvotes: 1
Reputation: 64363
I found a way to address my scenario using ERB.
I monkey patched YAML module to add two new methods
module YAML
def YAML.include file_name
require 'erb'
ERB.new(IO.read(file_name)).result
end
def YAML.load_erb file_name
YAML::load(YAML::include(file_name))
end
end
I have three YAML files.
mod1_config.yml
mod1:
age: 30
city: San Francisco
mod2_config.yml
mod2:
menu: menu1
window: window1
all_config.yml
<%= YAML::include("mod1_config.yml") %>
<%= YAML::include("mod2_config.yml") %>
Parse the yaml file using the method YAML::load_erb
instead of the method YAML::load
.
config = YAML::load_erb('all_config.yml')
config['mod1']['age'] # 30
config['mod2']['menu'] # menu1
Caveats:
Upvotes: 15
Reputation: 2108
I'm using this:
load_config.rb (initializer)
cf_1 = YAML::load(File.read("/etc/my_app/config.yml"))
cf_2 = YAML::load(File.read(File.join(Rails.root, "config", "config.yml")))
CONFIG = cf_1.merge(cf_2)
Later, you can access config values by doing:
CONFIG['value']
Upvotes: 2
Reputation: 12665
If your aim is avoiding duplication in your YAML file, not necessarily including external file, I recommend doing something like this:
development: &default
adapter: mysql
encoding: utf8
reconnect: false
database: db_dev
pool: 5
username: usr
password: psw
host: localhost
port: 3306
dev_cache:
<<: *default
new:
<<: *default
database: db_new
test:
<<: *default
database: db_test
Upvotes: 9
Reputation: 1646
Depends what you need it for. If you need to transport file, you can base64 encode internal yaml file.
Upvotes: 0