Install Ruby on Your Mac

Install Ruby on Your Mac: Everything You Need to Get Going

Chris Tobolski Developer Tips, Tricks & Resources

In this post, we’re going to show you how to install Ruby on your Mac. Along the way, we’ll learn about the steps involved and various bits of knowledge required to get up and going. So if you’re totally new, don’t worry! I’ll list each step and follow it with an “extra credit” section where I’ll explain that step in depth. If you’ve done this sort of thing before and just need some directions, I’ve included a TLDR section showing what commands to run.

Before we start…What is Ruby?

Ruby is an open-source programming language with a strong developer focus. Created in 1996 by Yukihiro Matsumoto, Ruby became really popular in the late 2000s with the introduction of the Ruby on Rails web framework. While Ruby is used quite frequently for web development, it’s also popular as a scripting language.

Ruby is known for being easy to learn and fun to use. So let’s find out how easy it is to get up and running!

What we’re going to do

  1. Open up the terminal
  2. Install a package manager
  3. Use the package manager to install Ruby
  4. Update our PATH
  5. Write and run our first Ruby program

What you’ll need

  • An internet connection
  • Administrator privileges (you should have this if you’re working on a personal device)
  • 15 minutes (or just a few if you only need the commands)

TLDR—Run these commands from the terminal

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
brew install ruby
echo 'export PATH="/usr/local/opt/ruby/bin:$PATH"' >> ~/.bash_profile
source ~/.bash_profile

Step 1: Open up the terminal

The terminal application on macOS is an operating system command line interface (CLI) that comes installed on new Macs. You can quickly open the terminal by doing the following:

  • Type ⌘+space bar. This brings up the macOS spotlight search, a search utility for opening apps on your Mac.
  • Type terminal into the spotlight search.
  • Press Enter.

Extra credit for step 1

When you open a terminal (assuming zero configuration), you start at your home directory. Did you know that a version of Ruby comes installed on your Mac by default? We can see that by typing some commands into our terminal. The which command allows us to see where on the computer an executable file lives.

which ruby

We passed Ruby as an argument, so the command is finding the Ruby executable location. If Ruby isn’t installed or available to us, the which command will let us know it couldn’t find Ruby.

Now let’s see which version of Ruby we have installed by typing in the following command:

ruby -v

Here, we’re invoking the Ruby CLI and passing the option -v to it. The -v option tells the Ruby CLI to return the version of the Ruby installation to us. If you don’t need the latest and greatest Ruby version, you could stop here. But as good software engineers and system administrators, we like to stay on top of things and install the updated versions when we can. Let’s do that by installing a package manager.

Step 2: Install a package manager

Hold on! What’s a package manager? A package manager is an application whose job is to manage software on your computer. In this case, managing means installing, updating, and removing software as needed. Package managers will install software in a consistent manner and keep your computer tidy.

As it turns out, macOS has an awesome package manager called Homebrew. Ironically, Homebrew is written in Ruby! Let’s get that installed.

The Homebrew homepage has the install information. We’re going to follow that by running this command in our terminal that we opened in step 1:

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

This command is going to install Homebrew for us. The cool thing about the Homebrew install script is that it will tell you what it’s going to do and prompt you for a yes or no before proceeding. The install script is very informative. One of the important things it points out for us will be that the install script is going to create some subdirectories in the /usr/ directory. More on that later.

Extra credit for step 2

Whoa! What’s that install command doing anyway? I’m a big proponent of understanding commands that you paste into your terminal before you run them. The terminal is a really cool and powerful program, but we can harm our machine if we paste someone’s malicious code in there, so it’s important to understand what we’re doing.

I look at this command and see a few notable things:

  • /usr/bin/ruby -e
  • curl -fsSL
  • curl is getting content from this address: https://raw.githubusercontent.com/Homebrew/install/master/install
  • The output of the curl command is interpolated for the Ruby command

Let’s explore what each of these mean

The /usr/bin/ruby portion of the command is giving our terminal a specific location to an executable. If you recall from our earlier step, when we used which ruby, we found that the Ruby command was coming from that same location in our bin directory. On Unix-like operating systems such as macOS, /usr/bin/ is where the operating system installs distribution executable files. Distribution executable files are executable files that come with and are managed by your operating system. Homebrew is using the absolute location to reliably call the Ruby command on a machine with unknown configuration.

I also notice that the Ruby command is getting called with the -e flag. If we type man ruby into our terminal, we can explore the documentation and find out what the -e flag does.

If we scroll down the man page to get to the -e flag, we’ll see that it says, “Specifies script from command-line while telling Ruby not to search the rest of arguments for a script file name.” To get out of the man page, just hit q.

To understand what that documentation means, you need to understand that the typical usage of the Ruby command would be to pass an executable Ruby file to it. So if I had a hello_world.rb file, I might type a command like ruby hello_world.rb, which would execute that file using Ruby. The -ecommand lets the Ruby CLI know that you want to treat whatever comes after the flag as the script to execute instead of looking for a file. We can test this out on our own by running an inline Ruby program!

ruby -e 'puts "hello world"'
hello world
The curl command

Alright. Now let’s look at the curl command. The curl command is actually cURL, which stands for “client URL.” The Homebrew install script uses curl to fetch data from GitHub.  The command is also using several flags. Again, we can use the man command and pass curl to it…which, while being slightly funny, is also super useful and can help us find out what these flags are doing. So here’s the condensed version of what we need to find in man curl.

  • -f means fail silently on server errors. This is to prevent seeing a text representation of an HTML server error document
  • -s means use silent mode. Silent mode doesn’t show the progress meter or error messages.
  • -S means show an error message if curl fails. It’s used to modify the -s option to still be silent unless the curl command fails.
  • -L is the location flag. This is a convenience flag to handle redirect HTTP response codes. If the document has moved and there’s a response indicating its new location, curl will go and try to fetch it at that location.

Cool. That was pretty straightforward. We’re fetching data with some flags that modify the way curl outputs status messages.

Fetching raw content from GitHub

If you actually paste the URL https://raw.githubusercontent.com/Homebrew/install/master/install into your browser, you’ll see that it brings up a Ruby script file. This is GitHub’s site that hosts raw files that are stored in a GitHub repository. It’s useful for fetching just the content of a script.

Interpolation, a fancy word for fancy folks

Oxford defines interpolation as “the insertion of something of a different nature into something else.” In our case, we’re doing string interpolation in Bash. We’re taking the output of one command and treating it like string input. In Bash, the best way to do string interpolation is to call a command from within a set of parenthesis preceded by a dollar sign. So since we’re wrapping the curl command in the parenthesis, like this…

$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)

…we’re treating the output like a string to the Ruby command.

Putting it all together

Ironically, we’re using Ruby to install the package manager, which we’ll use to install a newer version of Ruby!

  1. We’re calling the Ruby command and telling it to execute the content we’re passing to it instead of looking for a file.
  2. We’re pulling a raw Ruby script from https://raw.githubusercontent.com/Homebrew/install/master/install. And we’re doing it without any extra output from curl by passing those command line options. This is smart because the Ruby command wouldn’t know how to interpret any output from curl.
  3. We’re interpolating that script as input to the Ruby command!

Wow. There’s a lot to understand, even about relatively small commands! What I hope you take away from this section is that taking the time to understand some of the extra stuff is important and that the man command is your friend.

Now that we understand this step better, let’s actually install the latest version of Ruby.

Step 3: Use the package manager to install Ruby

Alright, so now that Homebrew is installed, we can use it to install a newer version of Ruby. The command is pretty straightforward:

brew install ruby

With this, Homebrew will go out and fetch not only Ruby but also any dependencies Ruby needs to run. On my machine, for example, Homebrew installed LibYAML prior to installing Ruby.

We’re almost ready to write our first Ruby program!

Extra credit for step 3

You’ll notice right now that if you run the ruby -v command again, it’s the same version of Ruby that we saw in step 1. What gives?

Homebrew was nice enough to tell us what happened. Here is a snippet of the output from the brew install ruby command:

ruby is keg-only, which means it was not symlinked into /usr/local,
because macOS already provides this software and installing another version in parallel can cause all kinds of trouble.

If you need to have ruby first in your PATH run:

echo 'export PATH="/usr/local/opt/ruby/bin:$PATH"' >> ~/.bash_profile
A brief look at how Homebrew installs programs

Remember earlier when I mentioned that package managers like Homebrew keep our machine tidy by installing things in a consistent manner? This output relates to that bit of information. When Homebrew installs a package, it will actually install it in a directory that Homebrew owns.

We mentioned that /usr/bin is for distribution executable files. There’s another directory, /usr/local/bin, that was created by Homebrew in step 2. Homebrew actually makes a directory named “Cellar” inside this directory. Homebrew will install packages into the Cellar and then make symlinks from those packages into /usr/local/bin that are available to us. A symlink, or symbolic link, is a special type of file that acts as a redirect to where the actual file lives. This allows Homebrew to be selective about what executables it makes available.

What does that mean for us?

It means that the newer version of Ruby is installed, but Homebrew isn’t going to put it on the PATH for us. It’s not going to do this because of the existing version of Ruby living in /usr/bin. It tells us how to fix this situation by modifying our PATH.

I’ve mentioned the PATH a lot, and we’re going to talk about it next!

Step 4: Update our PATH

The simplest way to do this is to follow the instructions Homebrew gives us. Run this command:

echo 'export PATH="/usr/local/opt/ruby/bin:$PATH"' >> ~/.bash_profile

This will update our Bash profile but not our current environment.

You could open a new terminal at this point, but a simpler method to update your environment is to run this command:

source ~/.bash_profile

The version of Ruby that is going to take precedence in the terminal is now the version we installed with Homebrew!

Verify that the new version is installed by again checking the version. It should be a more recent version than what was installed on the system by default.

ruby -v

Extra credit for step 4

There are some more interesting tidbits to unpack here.

  • PATH
  • echo and >>
  • ~/.bash_profile
  • source
The PATH variable

PATH is an environment variable. An environment variable is a piece of data that is available for both us and other subprocesses to use every time we open a shell prompt. The PATH contains a list of directories, separated by colons. When you type a command into your shell, it will look for executable files in those directories, in the order they listed.

The PATH variable serves a couple of purposes. One purpose is providing a single place to refer to and update an executable’s location. Also, the PATH makes our life easier by eliminating the need to refer to executables by their exact location. For example, if we had not followed step 4, we could still access the version of Ruby we installed, but it would be slightly annoying. If we wanted to check our newly installed Ruby version, we would have to refer to the command like this:

/usr/local/opt/ruby/bin/ruby -v

Now imagine typing that in everywhere! It’s not great, and it could also lead to a mess. If you decided to move that executable to another location, you’d have to type in that new location to reference the command. This would be a nightmare if scripts were using the absolute location. They would all break.

You can update your PATH by appending or prepending a directory to it. That’s what this section of the command is doing. It’s prepending a directory to the existing PATH variable.

export PATH="/usr/local/opt/ruby/bin:$PATH"
Echo and the >> operator

The echo command simply returns whatever we type in the shell back to us. For instance, you can run a command to print “Hello World” in the terminal:

echo "Hello World"
Hello World

The redirect operator used in conjunction with echo is a handy way to modify a file’s contents without opening the file. The >> operator tells the shell to append the output of the previous command to a given file.

This is what we’re doing. We’re appending export PATH=”/usr/local/opt/ruby/bin:$PATH” to the end of our Bash profile.

The Bash profile

The ~/.bash_profile is a special file that’s sourced when a new shell environment is created. The tilde at the start of that file is a directory alias for your home directory. For our purposes, you can think of this file as a place where you store user preferences when you create a new shell environment. This means that any time you open up the terminal program, anything you place in this file will run first. In this case, the PATH environment variable will be updated to prioritize the directory containing our version of Ruby.

Source

The source command takes a file and updates the current shell’s environment to contain any changes or additions in the sourced file. While our shell would source the Bash profile automatically when a new terminal is created, we can do it manually by running the source command ourselves.

Step 5: Write and run our first Ruby program

We’ve now installed Ruby!  Let’s celebrate by running the ceremonial and obligatory “Hello World” program. We’re going to use Vim, a commonly used editor for Ruby developers. Let’s open a file with Vim.

vim hello_world.rb

Now you have to type the character i to go into “insert” mode. Then go ahead and type the following:

puts "hello world"

Now let’s save and quit. Hit the Escape key, then type :wg and hit Enter.

Celebrate and type

ruby hello_world.rb

And that’s it!

There’s no extra credit here. We’ve already covered quite a bit of content. We set out to install Ruby, and along the way, we learned a little bit about several things:

  • Terminal
  • Package management
  • Shell commands
  • PATH
  • How to exit Vim 🙂
  • And more!

If you’re planning on using Ruby to write a cool business app, take a look at Retrace. Retrace can do all sorts of things for you, including helping you understand your application’s performance.

Start Free Trial

About Chris Tobolski

This post was written by Chris Tobolski. Chris is a full stack software engineer at FordLabs who enthusiastically practices lean validation while building human-centered products. He loves motivating teams and individuals to strive to reach their potential through continuous improvement. And while he’s a full stack engineer, he currently enjoys working with Typescript and React.