module HierarchicalConfig
Constants
- REQUIRED
- VERSION
Public Class Methods
from_hash_for_testing(hash, name='app', environment='test')
click to toggle source
# File lib/hierarchical_config.rb, line 116 def from_hash_for_testing(hash, name='app', environment='test') config, errors = lock_down_and_ostructify!( hash, name, environment ) raise errors.inspect unless errors.empty? config end
load_config( name, dir, environment, preprocess_with=:erb )
click to toggle source
# File lib/hierarchical_config.rb, line 62 def load_config( name, dir, environment, preprocess_with=:erb ) primary_config_file = "#{dir}/#{name}.yml" overrides_config_file = "#{dir}/#{name}-overrides.yml" config_hash = load_hash_for_env( primary_config_file, environment, preprocess_with ) if File.exists?( overrides_config_file ) overrides_config_hash = load_hash_for_env( overrides_config_file, environment, preprocess_with ) config_hash = deep_merge( config_hash, overrides_config_hash ) end config, errors = lock_down_and_ostructify!( config_hash, name, environment ) raise errors.inspect unless errors.empty? config end
load_hash_for_env( file, environment, preprocess_with )
click to toggle source
# File lib/hierarchical_config.rb, line 80 def load_hash_for_env( file, environment, preprocess_with ) file_contents = IO.read(file) yaml_contents = case preprocess_with when :erb ERB.new(file_contents).result when nil file_contents else raise "Unknown preprocessor <#{preprocess_with}>" end yaml_config = YAML::load(yaml_contents) ordered_stanza_labels = [] ordered_stanza_labels << 'defaults' if yaml_config.key? 'defaults' ordered_stanza_labels += yaml_config.keys.grep(/^defaults\[.*#{environment}/).sort_by{ |a| a.count(',') } ordered_stanza_labels << environment if yaml_config.key? environment config = deep_merge_hashes_in_keys(ordered_stanza_labels, yaml_config) env_config_labels = [] env_config_labels << 'env_vars' if yaml_config.key? 'env_vars' env_config_labels += yaml_config.keys.grep(/^env_vars\[.*#{environment}/).sort_by{ |a| a.count(',') } env_config = deep_merge_hashes_in_keys(env_config_labels, yaml_config) env_config = fill_in_env_vars(env_config) deep_merge(config, env_config) rescue StandardError => e raise <<-ERROR Error loading config from file #{file}. #{$!.inspect} #{$@} ERROR end
Private Class Methods
deep_merge( hash1, hash2 )
click to toggle source
merges two hashes with nested hashes if present
# File lib/hierarchical_config.rb, line 146 def deep_merge( hash1, hash2 ) hash1 = hash1.dup ( hash1.keys + hash2.keys ).each do | key | if hash1.key?( key ) && hash2.key?( key ) && hash1[key].is_a?( Hash ) && hash2[key].is_a?( Hash ) hash1[key] = deep_merge( hash1[key], hash2[key] ) elsif hash2.key?( key ) hash1[key] = hash2[key] end end hash1 end
deep_merge_hashes_in_keys(keys, root_hash)
click to toggle source
# File lib/hierarchical_config.rb, line 126 def deep_merge_hashes_in_keys(keys, root_hash) keys.inject({}) do |acc, label| deep_merge( acc, root_hash[label] ) end end
fill_in_env_vars(hash)
click to toggle source
# File lib/hierarchical_config.rb, line 132 def fill_in_env_vars(hash) r = {} hash.each do |key,value| if value.is_a? Hash leaf_hash = fill_in_env_vars(value) r[key]=leaf_hash unless leaf_hash.keys.empty? elsif !value.nil? && ENV.key?(value) r[key]=ENV[value] end end r end
lock_down_and_ostructify!( _hash, path, environment)
click to toggle source
Mutator method that does three things:
-
checks if any of the keys were required and not set. Upon finding
it adds key to the error set
-
recursively sets open structs for deep hashes
-
recursively freezes config objects
# File lib/hierarchical_config.rb, line 164 def lock_down_and_ostructify!( _hash, path, environment) hash = Hash[_hash.map{|k,v|[k.to_s, v]}] #stringify keys errors = [] hash.each do | key, value | hash[key], child_errors = lock_down_and_ostructify_item!(value, path + '.' + key, environment) errors += child_errors end return OpenStruct.new(hash).freeze, errors end
lock_down_and_ostructify_item!(value, path, environment)
click to toggle source
# File lib/hierarchical_config.rb, line 174 def lock_down_and_ostructify_item!(value, path, environment) errors = [] return_value = case value when Hash child_hash, child_errors = lock_down_and_ostructify!( value, path, environment ) errors += child_errors child_hash when Array value.each_with_index.map do |item, index| child_item, child_errors = lock_down_and_ostructify_item!( item, "#{path}[#{index}]", environment ) errors += child_errors child_item end.freeze when REQUIRED errors << "#{path} is REQUIRED for #{environment}" nil else value.freeze end return return_value, errors end