From 6f31a0bc000a6984bb77926cb1a71e48f8938177 Mon Sep 17 00:00:00 2001 From: Paul Annesley Date: Sun, 17 Mar 2013 01:32:52 +1100 Subject: [PATCH 1/2] Preprocess YAML files as ERB. This allows dynamic configuration files, and is in line with how Rails preprocesses database.yml as ERB. A primary use-case is configuration lines like: some_service: api_token: <%= ENV["SOME_SERVICE_API_TOKEN"] %> --- lib/configoro.rb | 1 + lib/configoro/hash.rb | 7 ++++++- spec/configoro/hash_spec.rb | 5 +++++ spec/configoro_spec.rb | 2 +- spec/data/config/environments/common/erb_test.yml | 2 ++ 5 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 spec/data/config/environments/common/erb_test.yml diff --git a/lib/configoro.rb b/lib/configoro.rb index 6b5cb2e..07fc834 100644 --- a/lib/configoro.rb +++ b/lib/configoro.rb @@ -1,5 +1,6 @@ raise "Configoro must be used in the context of a Rails 3 application" unless defined?(Rails) +require 'erb' require 'yaml' require 'bundler' Bundler.setup diff --git a/lib/configoro/hash.rb b/lib/configoro/hash.rb index b61d5ba..66cdbc2 100644 --- a/lib/configoro/hash.rb +++ b/lib/configoro/hash.rb @@ -30,7 +30,7 @@ def <<(hsh_or_path) when String raise ArgumentError, "Only files ending in .yml can be added" unless File.extname(hsh_or_path) == '.yml' return self unless File.exist?(hsh_or_path) - data = YAML.load_file(hsh_or_path) + data = load_preprocessed_yaml(hsh_or_path) deep_merge! File.basename(hsh_or_path, ".yml") => data when ::Hash deep_merge! hsh_or_path @@ -146,4 +146,9 @@ def remove_getter(meth) raise NameError, "undefined local variable or method `#{meth}' for #{self.inspect}" end + + def load_preprocessed_yaml(path) + YAML.load(ERB.new(IO.read(path)).result) + end + end diff --git a/spec/configoro/hash_spec.rb b/spec/configoro/hash_spec.rb index 547cf91..ea3122e 100644 --- a/spec/configoro/hash_spec.rb +++ b/spec/configoro/hash_spec.rb @@ -95,6 +95,11 @@ subject << "example.yml" subject.should be_empty end + + it "should preprocess YAML file as ERB" do + subject << "#{File.dirname __FILE__}/../data/config/environments/common/erb_test.yml" + subject.erb_test.sum.should == 2 + end end describe "#deep_merge!" do diff --git a/spec/configoro_spec.rb b/spec/configoro_spec.rb index 4c95f64..58a69e0 100644 --- a/spec/configoro_spec.rb +++ b/spec/configoro_spec.rb @@ -34,7 +34,7 @@ module MyApp; end it "should not complain when there is no directory for the current environment" do Rails.stub!(:env).and_return('unknown') Configoro.initialize - MyApp::Configuration.should eql({"basic"=>{"common_only"=>"common", "env_name"=>"common"}, "hash_test"=>{"akey"=>"value", "subhash"=>{"key1"=>"val1", "key2"=>"val2"}}}) + MyApp::Configuration.should eql({"basic"=>{"common_only"=>"common", "env_name"=>"common"}, "erb_test" => {"sum" => 2}, "hash_test"=>{"akey"=>"value", "subhash"=>{"key1"=>"val1", "key2"=>"val2"}}}) end end end diff --git a/spec/data/config/environments/common/erb_test.yml b/spec/data/config/environments/common/erb_test.yml new file mode 100644 index 0000000..242d6f5 --- /dev/null +++ b/spec/data/config/environments/common/erb_test.yml @@ -0,0 +1,2 @@ +--- +sum: <%= 1 + 1 %> From 9b8b4c8d9671445c24795612791dd9d728704454 Mon Sep 17 00:00:00 2001 From: Paul Annesley Date: Sun, 17 Mar 2013 02:04:14 +1100 Subject: [PATCH 2/2] README describes ERB preprocessing of YAML configuration files. --- README.textile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.textile b/README.textile index 64c0144..a329de0 100644 --- a/README.textile +++ b/README.textile @@ -70,6 +70,10 @@ Configuration is stored within the @config/environments@ directory of your Rails app. Files ending in ".yml" are loaded from the @common/@ subdirectory and a subdirectory named after the current environment. +Configuration files are preprocessed as ERB, in the same way that Rails +preprocesses @config/database.yml@. This allows dynamic configuration, +e.g. @host: <%= ENV["DB_HOST"] || "localhost" %>@. + Each file goes into its own hash in the configuration. For example, if you placed a file called @memcache.yml@ within @config/environments/development@, you would be able to access your Memcache timeout using