04 Sep 2011
RVM system gems without sudo
Somewhat unusually (I guess?) I sometimes use system Ruby on OS X. I use RVM for other versions of Ruby, like 1.9.2 and JRuby. System Ruby is still the easiest Ruby version to use on OS X, however. Furthermore, because it is so common with developers, I need to make sure that each new version of Bundler is compatible with OS X system Ruby.
System Ruby has a problem, though: it is hardcoded to install gem executables into /usr/bin
. This is very awkward because it means you need to run sudo gem install
so Rubygems can install the binaries. A less awkward setup (IMHO), is to leave /Library/Ruby/Gems/1.8 owned by the staff group, as it is in a fresh OS X install. In order to make that setup work, however, you have to override the Rubygems binary directory by adding -n/Library/Ruby/Gems/1.8/bin
to your ~/.gemrc
file, or pass that to the gem
command every time you run it. Once you add that directory to the front of your $PATH
environment variable, you’re set. Install gems without sudo, and everything is good.
This is all well and good until you install RVM and it tries to install gems for other versions of Ruby. Those other versions of Ruby will honor your ~/.gemrc
file and install your gem binaries into the system gems binary directory. In order to work around this, I have written an after_use hook for RVM. It redefines the gem
function that RVM sets up when you change between Ruby versions to include the -n option or not, depending on the version of Ruby that you have switched to. Here’s the code:
#!/usr/bin/env bash
if [ $rvm_ruby_string == "system" ]; then
function gem {
local result
command gem "-n/Library/Ruby/Gems/1.8/bin $@" ; result="$?"
hash -r
return $result
}
else
function gem {
local result
command gem "$@" ; result="$?"
hash -r
return $result
}
fi
In order to install it, run these commands:
curl http://bit.ly/after_use_system_binstubs > ~/.rvm/hooks/after_use_system_binstubs
chmod +x ~/.rvm/hooks/after_use_system_binstubs
Once the hook is installed, RVM will redefine the gem
function to include the -n option for system gem installs, and not include the -n option for non-system gem installs. It’s really pretty nice, since you no longer have to use sudo
to install any gems, system or not.