An environment variable is a key/value pair, it looks like this:
KEY=VALUE
We use these variables to share configuration options between all the programs in your computer.
That’s why it’s important to learn how they work & how to access them from your Ruby programs using the ENV
special variable.
Examples of environment variables:
- Configuring your default editor
- Telling Ruby where to find gems (
GEM_PATH
/GEM_HOME
) - Passing API keys into your application, without having to commit them to source control (git)
- Defining where your operating system should look for binary files (.exe in Windows)
- Making Rails start in test/development/production mode
You can find a list of ALL your environment variables with the env
command in Linux / Mac & the set
command in Windows.
Example:
PWD=/home/jesus SHELL=/usr/bin/zsh RUBY_ENGINE=ruby RUBY_VERSION=2.6.0 GEM_ROOT=/opt/rubies/ruby-2.6.0/lib/ruby/gems/2.6.0 # ...
The list can be pretty long, but you don’t have to memorize it.
You can also print all the gem-specific variables & configuration with the gem env
command.
Now:
If you want to access these environment variables from Ruby there is a special object you can use.
Let’s discover how it works!
Using Environment Variables in Ruby
Ruby has this ENV object that behaves like a hash & it gives you access to all the environment variables that are available to you.
Here are some examples…
You can find out how many keys you have:
ENV.size # 48
Get a list of them:
ENV.keys
And access specific keys:
ENV["GEM_HOME"] # "/home/jesus/.gem/ruby/2.6.0"
You can even use methods like map & select:
ENV.select { |k,v| k.size < 4 }
But how do you set these environment variables outside of Ruby?
How to Set Environment Variables
You can set an environment variable for a one time use.
Like this:
API_KEY=1 ruby -e 'p ENV["API_KEY"]'
Use this in a terminal, outside of irb, then Ruby will have access to this API_KEY
value.
This is helpful for API keys, but also to set Rails mode.
Example:
RAILS_ENV=production rails console
Remember:
This sets this specific environment variable for this process you’re launching now.
Meaning that if I do API_KEY=1 <command>
…
It will only work for that command!
If you want this variable to be used by all other commands that you launch from your current terminal session.
Do this:
export API_KEY=1
Now if you do:
ruby -e 'p ENV["API_KEY"]'
You’ll get 1
, even without the prefixed variable.
Warning:
Don’t use ENV
for configuration within your Ruby application, that’s NOT its purpose. ENV is only for reading external configuration coming outside of Ruby.
Try a gem like dry-configurable for internal configuration options.
Important Attributes of Environment Variables
You may find these attributes helpful because they explain (possibly unexpected) behavior.
- Snapshotting, environment variables are set when you launch a program & aren’t affected by outside changes
- Closed environment, changing variables inside a process (your Ruby program is a process) doesn’t change the environment variables outside the process
- Environment variables aren’t permanent, when you reboot your computer, or even when you close your terminal, changes to environment variables are lost (even if you use
export
Linux + Mac /set
in Windows)
Keep these in mind!
Rails Credentials
Rails 5.2 introduced a new system to help you manage API keys.
It works by saving the credentials directly to config/credentials.yml.enc
, this is an encrypted file that you can only read if you have the master.key
file.
The idea is that you only commit credentials.yml.enc
& you keep the key private.
How do you add new credentials?
Well, you can’t edit the .enc
file directly.
Use this command instead:
bin/rails credentials:edit
This is a YAML file, make sure to format it correctly.
Now:
You can read the credentials from your Rails app like this…
Rails.application.credentials.github_api_key
Watch Video Tutorial
Summary
You’ve learned about environment variables, a useful tool that allows you to manage your operating system configuration & keep your API keys private.
Please share this article with your friends so more people can find it 🙂
Thanks for reading!
Maybe because I’m french speaking, but I had to read this many time to understand the subtility. I understand this as “Don’t use ENV to put data at runtime”, but it’s not obvious. You should use envvars to build your application setup as 12factor third rule states: https://12factor.net/config
Yes, basically ENV should be read-only.
There are two gems that I use on a regular basis to work with environment variables inside of Ruby/Rails programs: nenv and dotenv
On my development workstation I use direnv to set/unset environment variables within the context of a directory.
Thanks for sharing what tools work for you. Haven’t heard of
direnv
before 🙂