Konfigurační soubor v Ruby on Rails
Při programování webových aplikací je často potřeba mít k dispozici hodnoty, které se za běhu aplikace nemění, konfigurační konstanty aplikace. Jak už to tak bývá, dají se v Ruby on Rails konstanty zadávat hned několika způsoby.
Já si vytvářím konfigurační soubor config/config.yml ve formátu YAML, kde mám konstanty navíc rozděleny na vývojové a produkční prostředí. Soubor má následující strukturu.
development: locales: ['cz'] currency: 'Kč' long_title: 'Eshop long title' short_title: Eshop short ga_id: xxx production: locales: ['cz'] currency: 'Kč' long_title: 'Eshop long title' short_title: Eshop short ga_id: xxx
Konfigurační soubor pak do Ruby on Rails aplikace načtu při jejím startu pomocí iniciačního souboru config/initializers/app_config.rb, ve kterém se vytvoří asociativní pole typu OpenStruct obsahující konfigurací, k níž pak přistupuji jakobych volal funkce třídy. Například AppConfig.currency (=> ‘Kč’). Všimněte si, že nemusím zadávat, zda chci hodnoty pro vývojové nebo produkční prostředí.
# Load application configuration require 'ostruct' require 'yaml' config = YAML.load_file("#{Rails.root}/config/config.yml") || {} app_config = config['common'] || {} app_config.update(config[Rails.env] || {}) AppConfig = OpenStruct.new(app_config)
Výše uvedený kód (který volně koluje po Ruby on Rails fórech) má ovšem i své nedokonalosti. Pokud chci konfigurační soubor s vnořenými hodnotami, viz ukázka, nemohu získat hodnotu voláním AppConfig.picture_style.large, ale musím použít AppConfig.picture_style[‘large’]. To se mi ale nelíbí.
development: locales: ['cz'] currency: 'Kč' long_title: 'Eshop long title' short_title: Eshop short ga_id: xxx picture_style: square: '150x150#' large: '280x280>' original: '840x840>' production: locales: ['cz'] currency: 'Kč' long_title: 'Eshop long title' short_title: Eshop short ga_id: xxx picture_style: square: '150x150#' large: '280x280>' original: '840x840>'
Aby se snadněji získávaly vnořené konfigurační hodnoty, musí se OpenStruct vytvořit v každém zanoření zvlášť. Iniciační soubor jsem si k tomu musel trochu přeprogramovat. Jeho základ nyní tvoří rekurzivní anonymní funkce, která projde konfigurační soubor a všude, kde je to možné, vytvoří asociativní pole typu OpenStruct.
# Load application configuration require 'ostruct' require 'yaml' config = YAML.load_file("#{Rails.root}/config/config.yml") || {} app_config = config['common'] || {} app_config.update(config[Rails.env] || {}) h2ostruct = lambda do | recurse, object | return case object when Hash object = object.clone object.each do |key, value| object[key] = recurse.call(recurse, value) end OpenStruct.new(object) when Array object = object.clone object.map! { |i| recurse.call(recurse, i) } else object end end AppConfig = h2ostruct[h2ostruct, app_config]