假设我的rails配置有一个yml文件......
settings.yml中
defaults: &defaults
interceptor_email: robot@wearemanalive.com
development:
<<: *defaults
test:
<<: *defaults
production:
<<: *defaults
我希望有另一个yml文件,它不包含在版本控制中,每个开发人员都在本地维护...
user_settings.yml
development:
interceptor_email: userfoo@domain.com
如何合并这些密钥?我正在用esb处理我的yml文件,所以这也是一个选项。只是无法弄清楚如何做到这一点。我有它的设置,所以如果我的环境缺少一个密钥,密钥会回退到默认值。
答案 0 :(得分:6)
你不能分别阅读这两个yml文件吗?
settings = YAML.load(path_to_settings)[RAILS_ENV].symbolize_keys
user_settings = YAML.load(path_to_user_settings)[RAILS_ENV].symbolize_keys
settings.merge!(user_settings)
现在您应该拥有设置的哈希值,然后您可以根据需要合并哈希值。如果第二个哈希与第一个哈希具有相同的密钥,则第一个哈希将被覆盖。
答案 1 :(得分:1)
我就是这样做的(免责声明,我刚刚写了它,所以它还没有进行单元测试等等......我会更新它,因为我改进了它):
require 'yaml'
# read config files (currently only yaml supported), merge user config files over
# defaults and make the parsed data available to the rest of your application.
#
module YourNamespace class Config
attr_reader :files, :get
# Accepts a string filename or an array of string filenames to parse.
# If an array is supplied, values from later files will override values
# of earlier files with the same name.
# Will choke if YAML.load_file returns false (invalid or empty file)
#
def initialize( files )
@files = files.respond_to?( 'map' ) ? files : [ files ]
@get = @files \
\
.map { | file | YAML.load_file file } \
.reduce( {}, :merge! )
;
end
end end
您可以这样称呼它:
config = YourNamespace::Config.new 'config.yml'
# or have the second one override the first
#
config = YourNamespace::Config.new [ 'config-defaults.yml', 'config.yml' ]
如果你想要看中,那里有很大的改进空间。理想情况下,将'Config'设置为不处理文件的接口,并在YamlConfig
,IniConfig
,CliConfig
,DbConfig
,CookieConfig
中实现。这样,如果你有一天决定新的配置格式超级种子yaml是如此酷,你可以很容易地改变它而不会破坏任何东西。您可以让命令行配置选项轻松覆盖来自配置文件的选项。无论配置值来自何处,您都可以将配置模块重用于任何ruby项目。或者也许只是停止inventing hot water。快速浏览让我觉得那里有一些非常热的水......
接下来编写一些文档,单元测试,输入验证,错误处理,并为配置值创建一些花哨的读/写访问器。也许您希望能够像这样要求配置值,而不是一直编写数组和哈希值:
config.get 'app.component.section.setting'
# or this if you want to keep them separate:
#
config.get( 'app', 'component', 'section', 'setting' )