In a recent conversation, we were discussing the practice that we should not store values such as API Keys in the configuration file, but instead load them from an environment variable. The reference was to how the
database.yml in Rails allows us to provide the details as environment variables in production. I needed to store some such values for some API tests that I was building using RSpec, and decided to find out how Rails does it – and realised that it’s blindingly obvious.
I’m just putting this here so that I remember it for the next time I need it – if it helps you, great… that’s a bonus!
If you’re using a normal YAML configuration file, you will be familiar with a code snippet that looks like this:
config = YAML.load_file(File.dirname(File.expand_path(__FILE__)) + '/../config/config.yml')
Basically, assuming you run this from the
/lib folder, you want to find the
config.yml file that is in the relative folder
../config form here, and load it using YAML. This returns a hash and you can then use the individual keys from there. For this, you would need your
config.yml to look something like this:
1 2 --- api_key: 'some-text-that-is-key'
Let’s say that we now want it to actually read something from the environment. In Ruby, you get access to the Environment Variables hash using
ENV – so, a value such as
SystemRoot set in the environment would be read as
ENV['SystemRoot'] into your program.
What we want to use is a YAML file that looks like this but, of course, regular YAML will not help read in the Environment Variable.
1 2 --- api_key: <%= ENV['APIKeyValue'] %>
What we want to do is get a way to execute the Ruby code to return the value of
ENV['APIKeyValue] and you’ll notice that the line looks a lot like ERB (if you’ve come across it). So, that’s the answer – we use ERB (Embedded Ruby).
Basically, we need to do this:
- Load the contents of the
config.ymlinto a string
- Use ERB to run the code
ENV['APIKeyValue]and produce a result with the value substituted
- Load that into YAML and parse it to get the configuration hash
This is what it would look like in simple step-by-step code:
1 2 3 4 5 6 7 8 require 'yaml' require 'erb' file = File.dirname(File.expand_path(__FILE__)) + '/config.yml') string = File.read(file) erb_out = ERB.new(File.read(File.dirname(File.expand_path(__FILE__)) + '/config.yml')).result config = YAML.load(erb_out) puts config['api_key']
or, in fewer lines:
1 2 3 4 require 'yaml' require 'erb' config = YAML.load(ERB.new(File.read(File.dirname(File.expand_path(__FILE__)) + '/config.yml')).result) puts config["api_key"]
That’s all there is to it!