Installing Gems
I have a command line utility written in Ruby, available as a Ruby Gem. I want to install it on my Mac OS X machine and make sure it is available in my $PATH. How should I go about doing this?
I am using RVM, but let’s ignore that for now.
Starting in Lion, with the default RVM Ruby set to system:
mark:~ $ gem install redwood
ERROR: While executing gem ... (Gem::FilePermissionError)
You don't have write permissions into the /Library/Ruby/Gems/1.8 directory.
OK. Now what?
If I go to the installation instructions for my favorite gem, I might see either sudo gem install my_favorite_gem or gem install my_favorite_gem.
In all of the instructions for gems that I have authored, I instruct the user to use the simple non-root gem install.
Why would you use sudo? When you run sudo you are running commands as root, another user in another shell. Maybe that works for a shared production or staging machine, but I’m trying to install a command line utility on my Mac.
Here’s what Homebrew says about using sudo to install packages:
Sudo is dangerous, and you installed TextMate.app without sudo anyway.
Here’s a great Stack Overflow answer about using sudo gem install:
The reason why installing gems with sudo is worse than just gem install is because it installs the gems for ALL USERS as root. This might be fine if you’re the only person using the machine, but if you’re not it can cause weirdness.
If you decide you want to blow away all your gems and start again it’s much easier, and safer, to do so as a non-root user.
sudo gem install seems to be able to do what I want, but with unforeseen consequences. And those are the worst kinds of consequences. Also, clearing out your gems and starting over again seems to happen much more often than one would think.
I use and like RVM, but I just want to install a command-line utility to be available system-wide. I don’t have strong opinions about which Ruby interpreter to use, I just want the executable available to me in my $PATH. RVM feels like overkill here. The way I see it, RVM’s main use cases are testing different libraries and applications across multiple Ruby environments, running an application in a sandboxed environment, and managing complex dependencies. RVM is not for users who care very little about what language a tool is written in. If a Perl user really wants to use ronn, it doesn’t make sense for them to download a Ruby Version Manager when they have a perfectly usable version of Ruby that came with their machine. RVM’s approach only obfuscates my task: get a command line utility installed.
So far, using plain gem install without the use of RVM on a machine running Lion is not going so well.
I really, really like Homebrew. I install all my other applications through there. I’d like my Ruby command line utility to fit in with the conventions prescribed by Homebrew.
hub is a great tool for extending git with github features. It’s a command line tool written in Ruby, but you can actually get it as a Homebrew Formula. The same goes for Chris’s gist tool. That’s great, but what about the incredibly useful command-line tool Ronn? No formula. There’s a really interesting pattern that you see with tools like gist and hub where a Rake task builds a standalone executable of the app perfect for packaging in a system like Homebrew, but its usage drops off when a tool has other gem dependencies, as is the case with ronn.1
I want to install my gem into the Homebrew toolchain using my Mac’s system Ruby. Some gems are available as Homebrew formula; others (the vast majority) are not.
Github’s Josh Peek created a plugin for Homebrew that allows you to install any rubygem as a formula. This is awesome. I recommend this approach. Here is a simplified view of what’s happening under the covers:
mark:~ $ gem install ronn --version 0.7.3 --install-dir `brew --cellar`/ronn/0.7.3
Installing the gem into the Homebrew Cellar, and then:
mark:~ $ brew link ronn
Linking /usr/local/Cellar/ronn/0.7.3... 3 links created
mark:~ $ which ronn
/usr/local/bin/ronn
Now ronn is nestled comfortably in Homebrew, and available on your $PATH.
But what happens when you run man ronn? You would expect Ronn’s man pages to come up, and Ronn has very good manpages. But when installing gems this way, there is no share/man directory, which is the default place brew link looks for man pages in. Right now, there is no automated way of getting your gem’s manpages into the right place, and that really sucks.
Why is this so hard? There are lots of resources for Ruby developers to learn about Gem authorship, but very little (if anything) dedicated to the user experience for this seemingly common use-case. Ruby is an excellent language for writing command-line tools, but distributing those tools to users in a convenient way (especially novice users or users who aren’t accustomed to the Ruby way) still has a ways to go before it feels simple.
tl;dr To install a Ruby command-line tool as a gem to your Mac, sudo can be dangerous and RVM is overkill. Homebrew is great and brew gem is a good step to the right solution, but it’s not quite there yet.
-
Subject for a future blog post about how Gem authors can set up these tasks. ↩