How I Installed Ruby 1.9.3

September 10, 2012 at 18:28:59

Don’t get the wrong idea; I’m not actually writing this in RubyFrontier from within Ruby 1.9.3. RubyFrontier isn’t ready for Ruby 1.9! But in order for RubyFrontier ever to have even a chance of becoming ready for Ruby 1.9, clearly I would sooner or later have to install Ruby 1.9. The problem, of course, is that I’m already using Ruby 1.8.7, and I need it for production work (like for using RubyFrontier and my various rb-appscript scripts); so the only way I can install Ruby 1.9 is if I have an easy way of switching back and forth between Ruby versions. I needed a Ruby version management system; and the much-ballyhooed RVM was not going to be it. Everything about RVM — the way it works under the hood, the zillions of posts about the issues it raises and the trickery needed to work around them — was opposed by every fibre of my intuition.

Then a few days ago I learned of rbenv, and I knew I wanted to try it right away. The simplicity and elegance of rbenv is simply breathtaking. It doesn’t do any of the scary, skanky things that RVM does. There’s a folder full of shim scripts masquerading as binary files such as ruby, which you add to the start of your PATH; that’s basically all. You install a version of Ruby into an ordinary folder in your .rbenv directory, and rbenv detects this. When you tell rbenv which version of Ruby you want to use, it changes the contents of a one-line configuration file called version. When you try to execute one of the binaries, what runs is the shim file, which creates an environment where the desired Ruby folder is now at the start of your PATH, and runs the real binary in that environment. For extra convenience you can also add a line to your .bash_profile to make certain things automatic, but they are all things you could equally have done yourself; no magic or swizzling is involved.

So my first step was to download rbenv from GitHub and follow the instructions for getting started. I then very conservatively installed my first new Ruby version — 1.8.7-p370, just a patch level or two above the 1.8.7 I’m already using — and everything went swimmingly. Well, actually there was a slight hitch: I tried to take advantage of an additional shortcut, ruby-build, which downloads, builds, and installs any version of Ruby into rbenv with a single command. Unfortunately, the build failed; the build and installation of Ruby itself worked, actually, but a second step, downloading and installing RubyGems, failed. My guess as to the reason for this is that ruby-build was downloading a version of RubyGems that was too old, RubyGems 1.6.2 — the current version is 1.8.24. So I submitted this problem as an issue and just went ahead and downloaded, built, and installed Ruby 1.8.7-p370 in accordance with the instructions that accompany rbenv (after cd-ing into its untarballed folder):

$ ./configure --prefix=$HOME/.rbenv/versions/1.8.7-p370
$ make
$ make install

Then I took a deep breath and asked rbenv to switch to the Ruby I had just installed:

$ rbenv global 1.8.7-p370

Sure enough, all indications were that I was now using that version of Ruby. So then I downloaded RubyGems and installed it (after cd-ing into its untarballed folder) by saying ruby setup.rb; this works because the ruby I’m talking about is now the right Ruby, so everything is installed in the right place. Sure enough, I was now able to install a gem, and it, too, went into the right place.

The next step was to see whether TextMate knew what had happened. It didn’t. For example, I was able to say this:

require 'rubygems'
require 'rails'

There was no error. But I hadn’t installed rails for this new Ruby version, so clearly we were still using the old Ruby. So I added the .rbenv/shim folder (where our ruby shim is) and the .rbenv/bin folder (where rbenv is) to the front of TextMate’s PATH shell variable, and tried again. Presto, we got an error: “no such file to load — rails.” But we could see the gem I had just installed. Evidently we were using the correct version of Ruby!

[There is still some work to do if you want to use ri with core classes in this new setup. You have to install the rdoc-data gem. I found that before I could successfully say rdoc-data --install so as to make the ri data be installed in the right place, I had to restart the computer; perhaps that was overkill, but apparently I needed to make the shell environment straighten itself out, or something.]

Elated by this success, I proceeded to download and install Ruby 1.9.3-p194 in the same way, and found myself in a complete mess. I’ll spare you the painful tale of how things went wrong one after another; I’ll proceed to what you have to do so that they won’t go wrong.

First, before trying to build Ruby 1.9.3-p194, you need to install LibYAML. Download it, untar it, cd into the folder, and do the usual dance:

$ ./configure --prefix=/usr/local
$ make
$ sudo make install

Now you can download and build Ruby 1.9.3, completely parallel to what we did earlier:

$ ./configure --prefix=$HOME/.rbenv/versions/1.9.3-p194
$ make
$ make install

Now switch to using that version of Ruby:

$ rbenv global 1.9.3-p194

A very recent version of RubyGems is already included, so test it by saying gem --version. This was the step that alerted me earlier to the fact that things had gone wrong. If you don’t have LibYAML in place at the time you build Ruby 1.9.3, it will fail to build and install the psych library (once an independent library, apparently, but now included with Ruby itself):

configuring psych
yaml.h is missing. Please install libyaml.
Failed to configure psych. It will not be installed.

Those lines will go by so fast you won’t even notice them, and the error isn’t outwardly fatal, but in fact this is bad because RubyGems in Ruby 1.9.3 wants psych, which needs LibYAML. RubyGems will work without psych, but you’ll get a warning every time you try to use it, which is maddening:

It seems your ruby installation is missing psych (for YAML output).
To eliminate this warning, please install libyaml and reinstall your ruby.

By installing LibYAML beforehand, we’ve eliminated that issue. I was so happy about this that I wrote a little note on StackOverflow about it. (The version of RubyGems included with Ruby 1.9.3 is a little behind, so we can bring it up to date at this point with gem update --system.)

Now we have to deal with TextMate. Everything appears to be just fine — TextMate is using Ruby 1.9.3 — until we encounter any kind of exception; an ordinary raise statement will suffice to demonstrate the problem. Instead of reporting the error message in orderly fashion, we get a horrifying segmentation fault from a script deep inside TextMate. Fortunately someone has been through all this and has put up a gist file for fixing the problem, at Open the TextMate application bundle and drill down to the troublesome script, Contents/​SharedSupport/​Bundles/​Ruby.tmbundle/​Support/​RubyMate/​catch_exception.rb. Substitute the contents of the gist for the contents of this script. (If you don’t want to, then comment out what’s there, or devise some version-dependent way of switching between what’s there now and what’s in the gist.) Presto, Ruby 1.9.3 is running in TextMate.

I’ve now tried this technique both on Mac OS X 10.6.8 and on Mac OS X 10.8.1 and it’s working fine on both. Now I can play with Ruby 1.9!


This page prepared February 14, 2014 by Matt Neuburg, phd = matt at tidbits dot com, using RubyFrontier. RubyFrontier is a port, written in the Ruby language, of the Web-site-creation features of UserLand Frontier. Works just like Frontier, but written in Ruby!
Download RubyFrontier from GitHub.