рельсы: слияние yml - PullRequest
       17

рельсы: слияние yml

4 голосов
/ 31 марта 2011

Скажем, у меня есть файл 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

Как я могу объединить эти ключи? Я обрабатываю свои файлы yml с помощью esb, так что это тоже вариант. Просто не могу понять, как это сделать. Я настроил его так, чтобы ключи возвращались к значениям по умолчанию, если в моих средах отсутствует ключ.

Ответы [ 2 ]

6 голосов
/ 31 марта 2011

Разве вы не можете прочитать два файла 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 голос
/ 01 мая 2014

Вот как я это делаю (заявление об отказе, я только что написал, так что у него еще нет модульных тестов и т. Д. ... Я буду обновлять его по мере его улучшения):

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. Таким образом, если вы когда-нибудь решите, что новый формат конфигурации super seeding yaml - это круто, вы можете легко изменить его, ничего не нарушая. И вы можете сделать так, чтобы параметры конфигурации командной строки легко переопределяли те, которые поступают из файлов конфигурации. И вы можете повторно использовать модуль конфигурации для любого проекта ruby ​​независимо от того, откуда поступают значения конфигурации. Или, может быть, просто прекратите изобретать горячую воду . Быстрый просмотр заставляет меня думать, что там довольно горячая вода ...

Далее напишите некоторую документацию, модульные тесты, проверку входных данных, обработку ошибок и создайте некоторые модные средства доступа для чтения / записи для значений конфигурации. Возможно, вы захотите иметь возможность запрашивать значение конфигурации, подобное этому, вместо того, чтобы постоянно писать массивы и хэши:

config.get 'app.component.section.setting' 

# or this if you want to keep them separate:
#
config.get( 'app', 'component', 'section', 'setting' ) 
...