Skip to main content
64 Rails Concepts:

Environment Variables

Episode 1 · July 2, 2014

A look at how you can store API keys and other variables in the environment on different computers.

Basics


Transcripts

What are environment variables?

Well environment variables are a construct inside your operating system that allow you to create these variables that all of your applications can use.

One of them that you probably have seen around is the dollar sign path variable.

$Path

Now this variable defines a set of paths that your terminal looks at for executables in your operating system.

So if we echo out the path variable...

In terminal type:

echo $PATH

we can see the value thats saved in there.

Output from terminal:

 /Users/chris/.rbenv/shims:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin

Each of these folders is separated by a colon.

When you type a command like ruby into your terminal...

In terminal type:

ruby

it will go through the first folder and check to see if there’s a ruby command in there. If there is not it will go to the next one and look to see if there is ruby in there; and the next one, and so on. If it gets through all of them and it doesn't find any ruby command then it will just give you an error and say that there is no such file or directory.

If we type...

In terminal type:

ruby -v

I get output and its actually from ruby. So what we can do to see what's going on; is if we list out this first folder...

In terminal type:

 ls Users/chris/.rbenv/shims

we can see in here that there's a whole bunch of executables; and one of those is ruby. So this one is RBENV’s versions of ruby that it’s provided me; and with RBENV I have set the version to 2.1.2

Now RBENV, and RVM, and these other applications hook into this so that we can have multiple versions of ruby running on our computer. We can switch between them; and the path variable here is what RBENV uses to insert itself at the very beginning. When you type rails, or rake, or Ruby, or any of these commands they will first hit RBENV’s version and run that before it gets into any of the ones installed on the rest of your system.

So environment variables are really interesting, and we can take this and use them in our own applications. So in your rails application you have a database password and possibly API keys for different things like Twitter, or Facebook, or your email server that’s running SMTP for example. So these passwords and API keys you don’t necessarily want to store in your code inside your rails application; or your git repository, and you definitely don't want to do that if your rails application is public.

So how do we go about setting these variables that we sort of want to have just on our computer but not inside of our code?

Well thats what environment variables come in really handy for. So if we have a password environment variable...

In terminal type:

 PASSWORD=password irb

and when we set it equal to password, and we type irb...

("And in this case we don’t have a dollar sign because you use a dollar sign when you access it from the terminal. So It gets a little confusing. Sometimes you use the dollar sign; sometimes you don't. But when you want to print out in the terminal that's usually when you wanna use it. And in ruby and these other applications you don't need it.")

So once we set PASSWORD=password irb we can see here that if we type ENV and we pass in the key...

In terminal type:

 ENV[“PASSWORD”]

ENV is the hash of all the environment variables that we have available so if we type that in we can get password back. If we want to take a look at ALL of them we can type in just env.

In terminal type:

ENV

And we can see that we have the RBENV version, where RBENV’s root is, and all of these other variables.

So you can see that I have set up the one before with my email address. You can see what my user is, and my home directory, and so on. So it sets a whole bunch of these and we have access to all of them which is really cool.

So when we do this again and we say password equals password...

In terminal type:

PASSWORD=password

then we want to do some work; we want to run our ruby and grab this password variable like we did before. But We’re gonna run into a problem.

In terminal type:

irb

In terminal type:

ENV[“PASSWORD”]

Its nil because we set this. It sets it once for this command thats run in the terminal. Then its cleared out. It's only a temporary assignment. Which is kind of a problem.

We want to be able to set this for a long period of time like these other ones. For example if I echo home; we want this to be permanent so that we can see this every single time we run it.

In terminal type:

 exit

In terminal type:

 echo $HOME

So in order to make these permanent we need to use export.

Now the export command is going to basically put this into the environment permanently; at least for this session. It won’t actually be permanent; but it will be for this session. So if we say...

In terminal type:

export PASSWORD=password

we can type irb now and load up the password variable without a problem.

In terminal type:

 irb
ENV[“PASSWORD”]

So we can share that now between commands in our session. The problem is that we set this export password; but if we do it in a new terminal and we load up the password variable; it’s nil again.

In a new terminal type:

 irb
 ENV[“PASSWORD”]
exit

So how do we fix this?

The way to actually set these permanently to be loaded every single time that our terminal loads is to put it inside of our terminals config file.

Now by default you're probably using bash. So if you're on linux you'll want to edit the .bashrc file. If you're on a mac you'll want to do the .bash_profile file. if you're using zsh you'll want to do your .zshrc file. So im going to open up my .zhsrc file.

If you're using zsh then in your terminal type:

 mvim .zshrc

Now they're all basically the same. They take commands and you put these in, and they'll just be loaded when your terminal loads. So as you can see I have some configuration stuff for zsh. I have my own theme and it loads zsh. At the end here it loads RBENV. So if we want to we can say...

In your zsh file write:

export PASSWORD=password

at the end here and save this file. Now we can open up a new terminal. Then we can open up IRB and type in the ENV password just like we had before and it will actually load the password.

In terminal type:

 irb
 ENV[“PASSWORD”]

SO this is how we can configure our operating system to load that variable every time that we start a terminal session. Then we can access that every single time with no problems. So this is one way that RBENV and RVM enters. They inject themselves into your system by adding these load scripts into your .bashrc Or Your .zshrc file.

For Example:

If which rbenv > /dev/null; then eval “$(rbenv init -);

SO these commands are basically doing the same sort of thing here... export PASSWORD=password but instead they are modifying your path variable to add themselves to the beginning.

So to Recap:

Environment variables are really useful for setting passwords in your env; that way you don't have to set them inside your rails application code. They are also really useful for our ruby version management tools; such as RVM or RBENV, to inject themselves into your terminal which allows a pretty seamless experience shifting between ruby versions.

These tools that use environment variables are extremely useful, and something that is a little bit outside of the regular ruby learning tools and content. However; they are really important and used in a lot of places. They are more pure linux or operating system specific things; but they are really useful for you to be able to understand and take advantage of when you’re building software.

Transcript written by Timothy Ashby

Discussion


Fallback

I always found Env Variables very confusing, this does help. However still not a 100% sure if I'm use this method over something like Figaro.
Also how do I push these to Heroku?

Fallback

Figaro and the new Rails 4.1 secrets.yml are ways to manage these. This episode is intented to explain what they are so when you run into things like Figaro and secrets.yml you have a better idea of what you're looking at.

Heroku has a config command that lets you view and set environment variables. More info here: https://devcenter.heroku.co...


Login or create an account to join the conversation.