Ruby on Rails: Use environment variables instead of environment names

Let’s put Ruby aside for a minute, close our eyes, and think of the times we write in JavaScript… Remember how we used to guess a browser’s capabilities based on its name and version? That quickly became a bad idea, which let us to check for the presence of the actual features instead of assuming they were there based on the reputation of the browser.

Now back in the world of Ruby on Rails. I notice we may rely a bit too much on the name of the environment, like staging or production, to enable to disable certain features. Sometimes, especially for testing or troubleshooting, it would be nice to quickly toggle such a setting based on environment without having to change lines of code, commit, run tests, and deploy.

Here is my suggestion: instead of using the environment’s name to shape the configuration of the Ruby on Rails app, use environment variables.

On development, as I explain in another article, I use dotenv to store environment variables in a text file locally. This matches how Heroku works with those variables while running my app on their servers. (Instead of dotenv, you can also try Figaro.)

The config/environments/*.rb files are fine where they are. But often, instead of changing environment config files, I write a new one in config/initializers and check the value of an environment variable to enable or disable a feature.

For example, I have this file to force SSL on my app:

Rails.application.configure do
  config.force_ssl = (ENV['FORCE_SSL'] == '1')

Instead of using Rails.env and assume I only want SSL on production, I only need to set FORCE_SSL to 1. If I want to disable SSL on staging or production, I simply have to delete the variable or set it to any other value. Similarly for development, if I want to test SSL connections, I can simply set the value. In your code, just be sure to always check for a string or nil, like the above '1', since you’ll never get an integer from environment variables – only strings or nothing at all.

Since I have to restart the app when changing that configuration anyway, I find this method quicker than having to edit the code every time. Also, on Heroku, changing the value of an environment variable will automatically restart the app.

This method has come really handy for me. They affect many aspects of my app, including the following:

  • force SSL connections,
  • gzip compression,
  • use local or remote SSL server,
  • catch all e-mail messages and forward them to administrators,
  • time zone,
  • etc.

There are many cases in which you can use environment variables. It’s not much work to implement, and I’m sure you’ll love the time it’ll save you!