How to include a YAML file inside a YAML file in Ruby
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 simil开发者_StackOverflowar 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.
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 ...
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:
- Does not support document merge
- Last include overwrites same named keys
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
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
Usage
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.
Examples
# start.yml
extends: 'super.yml'
data:
name: 'Mr. Superman'
age: 134
favorites:
- 'Raspberrys'
-
# super.yml
data:
name: 'Unknown'
power: 2000
favorites:
- 'Bananas'
- 'Apples'
Basic Inheritance
YAML.ext_load_file('start.yml')
results in
data:
name: 'Mr. Superman'
age: 134
power: 2000
favorites:
- 'Bananas'
- 'Apples'
- 'Raspberrys'
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']
!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.
Depends what you need it for. If you need to transport file, you can base64 encode internal yaml file.
精彩评论