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.
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!
/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
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:
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.
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:
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.
For Mac M1, it returns the following:
ruby 2.6.10p210 (2022-04-12 revision 67958) [universal.arm64e-darwin22]
That means M1 Macs come with Ruby version 2.6 installed.
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.
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:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
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 /bin/ directory. More on that later.
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:
The /bin/bash portion of the command is giving our terminal a specific location to an executable using the bash command. If you recall from our earlier step, when we used which ruby, we found that the Ruby command was coming from the location /usr/bin/ruby 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.
I also notice that the Ruby command is getting called with the -c flag. If we type man ruby into our terminal, we can explore the documentation and find out what the -c flag does.
If we scroll down the man page to get to the -c flag, we’ll see that it says, “
Causes Ruby to check the syntax of the script and exit
without executing. If there are no syntax errors, Ruby
will print “Syntax OK” to the standard output.
” To get out of the man page, just hit q.
As the documentation suggests, the above command simply checks the syntax of the Ruby script and prints a standard output “Syntax Ok” if the syntax is correct.
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.
Cool. That was pretty straightforward. We’re fetching data with some flags that modify the way curl outputs status messages.
If you actually paste the URL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh 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.
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/HEAD/install.sh)
…we’re treating the output like a string to the Ruby command.
Ironically, we’re using Ruby to install the package manager, which we’ll use to install a newer version of Ruby!
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.
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!
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 /opt/homebrew, 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="/opt/homebrew/opt/ruby/bin:$PATH"' >> ~/.zshrc
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 the distribution of 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.
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!
The simplest way to do this is to follow the instructions Homebrew gives us. Run this command:
echo 'export PATH="/opt/homebrew/opt/ruby/bin:$PATH"' >> ~/.zshrc
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:
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.
And now you’ll see the newer version of Ruby returned by the above command that you just installed:
ruby 3.2.2 (2023-03-30 revision e51014f9c0) [arm64-darwin22]
There are some more interesting tidbits to unpack here.
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 to provide 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:
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.
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"
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 ~/.zshrc 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.
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.
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.
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 :wq and hit Enter.
Celebrate and type
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:
Try Stackify’s free code profiler, Prefix, to write better code on your workstation. Prefix works with .NET, Java, PHP, Node.js, Ruby, and Python.