The Ruby VM market is thriving, and we increasingly find ourselves spending the morning in JRuby and the afternoon in Ruby Enterprise Edition. Or Thursday using Leopard Ruby and Friday using Ruby 1.9. Or … well, you get the idea. So we needed a lightweight tool that eliminates the cost (in both time and frustration) of switching between Ruby versions. We wanted something drop-dead simple. Meet the Ruby Switcher.

Ruby Switcher

Hello, Ruby Switcher

The Ruby Switcher debuted earlier this year as a means for toggling between a handful of pre-installed Ruby versions. And once you bit the bullet and manually installed those VMs, and assuming you installed them in the “right” location, the Ruby Switcher offered crazy-fast switching between those few Ruby versions. But we’re passionate about continuous improvement and maintaining a sharp set of tools, so we recognized that switching Ruby versions was Step 2; Step 1 (i.e., installing those Ruby versions in the first place) needed a healthy dose of automation as well. Today’s Ruby Switcher makes both steps insanely simple, and it adds support for more (and newer) Ruby versions as well.

Pick a Ruby, Any Ruby

Enough talk! Let’s download the Ruby Switcher and get this party started.

cd
curl -O -L http://github.com/relevance/etc/raw/26ae85c2f6c7d2640a3c75d619ad7ab8fc1cc570/bash/ruby_switcher.sh
echo "source ~/ruby_switcher.sh" >> .bash_profile
source .bash_profile

That’s it. Let’s quickly verify that you have your platform’s core developer tools installed, and then you’ll be ready to put the Ruby Switcher to work.

Prerequisites - Compilers, Libraries, and Whatnot

If you’re on OS X, you’ll need to download and install Xcode. (If you just want to switch between Leopard Ruby and JRuby, you can skip this step. If you want to use any other versions of Ruby, you’ll need Xcode.)

If you’re using Ubuntu, use apt-get to grab a few essential packages:

sudo apt-get update
sudo apt-get install build-essential zlib1g-dev libreadline5-dev libssl-dev

For other *nix variants … well, clearly you enjoy figuring this stuff out.

Ruby 1.9

Yehuda Katz recently asked the Ruby community what we need in order adopt Ruby 1.9. Having an easy way to experiment with Ruby 1.9 is surely a good place to start. What could be easier than a single command?

install_ruby_191

The installation will take a few minutes. In the meantime, why not check out Bruce Williams’ slides on Ruby 1.9 from last year’s Lone Star Ruby Conference — Ruby 1.9: What’s New and Why it Matters?

...
checking build system type... i686-pc-linux-gnu
checking host system type... i686-pc-linux-gnu
checking target system type... i686-pc-linux-gnu
checking for gcc... gcc
...
installing rdoc
Using ruby 1.9.1p129 (2009-05-12 revision 23412) [i686-linux]
Successfully installed rake-0.8.7
1 gem installed

By the time you’re done reading through the Ruby 1.9 highlights, you’ll be ready to take it for a spin. Type ruby -v to verify that you’re rockin’ with 1.9.1.

ruby 1.9.1p129 (2009-05-12 revision 23412) [i686-linux]

JRuby

Installing and using JRuby is just as easy.

First, be sure that you have the JDK installed. If you’re using OS X, you’re all set. If you’re on Ubuntu, you can install it with apt-get. (For other Linux distros, you can ask your native package manager for the JDK bits.)

sudo apt-get update
sudo apt-get install sun-java6-jre sun-java6-jdk

With the JDK in place, installing JRuby is a cinch.

install_jruby

Verify the results with ruby -v.

jruby 1.3.1 (ruby 1.8.6p287) (2009-06-15 2fd6c3d) (Java HotSpot(TM) Client VM 1.6.0_10) [i386-java]

Wait a minute: shouldn’t we have typed jruby -v instead of ruby -v? Sure you can do that if you really want to. But we’re not big on having to remember to type jirb instead of irb, or jgem instead of just gem, etc. Once we tell the shell to use JRuby, we want the normal Ruby commands to just work. The Ruby Switcher ensures that they do.

Ruby.*

Looking for yet another Ruby version? See what else the Ruby Switcher has to offer:

  • install_ree_186
  • install_ruby_186
  • install_ruby_187
  • install_jruby_120

And if you find yourself wanting some other Ruby variant, be sure to check out the Ruby Switcher’s internals; you can likely adapt one of the existing installation functions to meet your exact need.

Willy-nilly Switching

Once you have the desired Ruby versions installed, switching between them couldn’t be easier. Each of the install commands comes with a corresponding use command to instruct your shell to switch to the specified Ruby version:

Install It Use It
install_ruby_191 use_ruby_191
install_ruby_186 use_ruby_186
install_ruby_187 use_ruby_187
install_jruby use_jruby
install_jruby_120 use_jruby_120
install_ree_186 use_ree_186
N/A [1] use_leopard_ruby

And these commands are shell-specific! So while one terminal window is using Ruby 1.8.7 to run your front-end Rails app, you can have another terminal using JRuby to run your back-end messaging code.

Ruby 1.9, the Community, and You

Want to see whether your app runs on Ruby 1.9? Flip your shell to use_ruby_191 and try it out. It’s that kind of experimentation that will allow the Ruby community to make the migration to Ruby 1.9.

See a problem with a certain gem on Ruby 1.9? Let the gem author know about it and chime in at isitruby19.com. Better yet, write a test that proves the bug and pass that test along to the author. Better still, fix the issue and submit a patch. Any one of these steps moves us forward, and all the while you’ve still got your default Ruby installation standing safely by for your day job.

When switching between Ruby versions is this seamless, there’s no reason not to experiment.

Notes

[1] Ruby is installed by default on OS X Leopard, so there’s no need for an install_leopard_ruby command.

Image courtesy of bdu (flickr.com/bdu). [Creative Commons License]

Comments
  1. Erik RunyonJuly 29, 2009 @ 11:42 AM

    If the ruby versions are shell-specific, how do you handle cases such as: 1. You want to test a development site using Passenger with a specific Ruby 2. Can you specify a version of Ruby to use when running tests in Textmate using command-r?

    Thanks.

  2. NickJuly 29, 2009 @ 12:32 PM

    Awesome!!!!

  3. Matthew McCulloughJuly 29, 2009 @ 11:13 PM

    Even though you guys are the Ruby pros leveraging use_ruby_XXX, in some ways, this is actually a tool that provides the most value for Ruby novices like myself. When learning Ruby, it seems that each book or tutorial has an expectation on a given version. This makes aligning with book samples trivial. Thanks!

  4. Aaron QuintJuly 30, 2009 @ 01:39 AM

    Very Cool! You might want to change:

    echo “source ~/ruby_switcher.sh” >> .bash_profile

    to

    echo ”\nsource ~/ruby_switcher.sh” >> .bash_profile

    As it pushed the source command on the same line as the last line in my bash_profile

  5. Donald ParishJuly 30, 2009 @ 02:30 AM

    Thanks! I’d played with Ruby 1.9 before, but installing was a bit of a pain. This will make it easier to test patches to Rails, too.

  6. SofiJuly 30, 2009 @ 01:50 PM

    Yeah! great post, everything works as i thought

  7. Patrick HurleyJuly 30, 2009 @ 02:36 PM

    Just a quick thank you, this works really well. I had something similar hacked together, but not nearly as comprehensive. Also this makes setting up new machines a breeze.

  8. anonymous cowardJuly 30, 2009 @ 07:00 PM

    yay, 808!

  9. Jason RudolphAugust 01, 2009 @ 02:01 PM

    @Erik Runyon,

    It would be nice to be able to quickly change the Ruby version in use by Passenger. I haven’t tried that yet, but this [1] looks like the right starting point.

    TextMate uses a shell variable called “TM_RUBY” (available in the “advanced” tab of the TextMate Preferences) to determine which Ruby to use. You could probably set up some TextMate commands to make it easy to quickly change that value to Ruby 1.9.1, JRuby, etc. (We tend to run our tests from the command line with beholder [2], so this isn’t an itch we’ve felt the need to scratch just yet.)

    If you dig into either of these items, please let us know what you find.

    [1] http://www.modrails.com/documentation/Users%20guide.html#specifying_ruby_installation

    [2] http://github.com/spicycode/beholder

  10. Dalibor NasevicAugust 02, 2009 @ 02:39 PM

    It works! Very good and secure way for the community to move to ruby 1.9.1. Thanks!

  11. Dr NicAugust 04, 2009 @ 09:21 PM

    Oh this all colours of awesomeness.

  12. Ben ReubensteinAugust 05, 2009 @ 01:15 AM

    This is just the tool I have needed. Two notes:

    The default ruby is always set to leopard ruby in the script, simply replace the last line with the use_ command you prefer.

    I had settings in .bash_login that were ignored after adding the .bash_profile, I simply moved the necessary line to .bash_login.

  13. VentegoAugust 05, 2009 @ 08:22 AM

    Thank you! You often write very interesting articles. You improved my mood.

  14. James HillAugust 05, 2009 @ 09:10 AM

    Good stuff, this has made my day.

    One error in the use_ruby_191 function:

    “export GEM_HOME=/.gem/ruby/1.9” should read “export GEM_HOME=/.gem/ruby/1.9.1”

  15. Andrew Montgomery-HurrellAugust 05, 2009 @ 09:14 AM

    Looking at your script, it looks like you’re using the same gem directory for all the various ruby 1.8 installs. I was under the impression this would cause problems fr gems with native extensions due to various issues, as mentioned here about REE http://www.rubyenterpriseedition.com/documentation.html#_how_ree_installs_itself_into_the_system

    Have you found that in practice this isn’t an issue?

  16. Mathieu MartinAugust 05, 2009 @ 01:44 PM

    I’ve been putting off using REE on my dev machine for so long… But you know, I’m lazy and busy.

    Now with 2 commands that worked flawlessly I got it up and running :-) Thanks guys!

  17. jptixAugust 06, 2009 @ 12:07 AM

    You can make sure to grab the latest version of the script by using this URL instead

    http://github.com/relevance/etc/raw/master/bash/ruby_switcher.sh

    Perhaps the script should have a function fetch_latest_ruby_switcher() ?

  18. RenokeAugust 06, 2009 @ 12:58 PM

    Awesome !

    On my side, I installed manually the different version and write aliases in my .bash_login file who switch a single symlink to the different versions. For exemple :

    alias use_ruby_187=’sudo ln -fhs /usr/local/ruby-1.8.7-p72 /usr/local/ruby’

    alias use_ruby_191=’sudo ln -fhs /usr/local/ruby-1.9 /usr/local/ruby’

    There also multiruby gem http://blog.zenspider.com/2007/12/testing-for-ruby-18-and-19-usi.html who makes a good job as well.

  19. sandroAugust 09, 2009 @ 01:31 AM

    I’m not sure if this matters in 1.9 but you may consider adding the—disable-pthread flag during configuration which typically yields a 30% speed increase.

  20. Excellent!August 09, 2009 @ 06:55 PM

    This is terrific (Although I did have a problem installing REE, and sent you the ‘relevance’ user on GitHub an email about that, a pointer to a bug tracker would be nice).

    And you’ll be happy to note that I tested a gem project I manage and discovered a couple of tiny incompatibilities with 1.9.1 which are now fixed and the gem is tested in 1.8.6, 1.8.7, 1.9.1 and Leopard Ruby. I feel much better now. Thanks.

    Some tips on using various ruby versions with Passenger/Textmate would be much appreciated.

  21. Jason RudolphAugust 14, 2009 @ 07:38 PM

    @Andrew – Thanks. That issue is fixed in the latest version.

    REE’s gems now live in: ~/.gem/ruby-enterprise/1.8

    Commit: http://is.gd/2h2io

    Latest Version: http://is.gd/2h2mD

  22. Jason RudolphAugust 14, 2009 @ 07:51 PM

    @Glenn – I tried recreating the REE installation error on a clean OS X image, but I was unable to reproduce the problem.

    Are you still seeing this problem?

    Cannot install the memory allocator for Ruby Enterprise Edition

    This installer was able to compile the memory allocator for Ruby Enterprise Edition, but could not install the files to ~/.ruby_versions/ruby-enterprise-1.8.6-20090610.

    This installer probably doesn’t have permission to write to that folder, because it’s running as glenn. Please re-run this installer as root.

    Are their any custom permission settings for your user account? It seems odd that you wouldn’t be able to write to your own home directory.

  23. danAugust 15, 2009 @ 07:58 AM

    I want to test my site with 1.9. when i type gem list it only have rake. Can I share my old gems or do I have to install all the gems? how do i install gems? can i use rake gems:install?

    thank you!

  24. Glenn RempeAugust 16, 2009 @ 12:10 AM

    Hi Jason,

    I mentioned to you in GitHub email that the problem went away mysteriously (problem installing REE related to installation of memory allocator). I wanted to report that I did a clean install (erase and install, not upgrade) of Snow Leopard today on my laptop, and with nothing installed or configured other than XCode dev tools I saw the same error pop up when trying to install REE. The others installed clean. Cheers.

  25. David ReeseAugust 16, 2009 @ 04:07 PM

    A note to passenger users—in addition to specifying your PassengerRuby, you’ll also need to specify a couple environment variables first:

    1. SetEnv MY_RUBY_HOME ~/.ruby_versions/ruby-1.9.1-p129 # maybe unnecessary?
    2. SetEnv GEM_HOME ~/.gem/ruby/1.9.1 # note this location is for the most recent ruby_switcher.sh—previous versions used ~/.gem/ruby/1.9

    Then you’d have something similar to this (this is what passenger-install-apache2-module feeds you):

    1. LoadModule passenger_module /Users/david/.gem/ruby/1.9.1/gems/passenger-2.2.4/ext/apache2/mod_passenger.so
    2. PassengerRoot /Users/david/.gem/ruby/1.9.1/gems/passenger-2.2.4
    3. PassengerRuby /Users/david/.ruby_versions/ruby-1.9.1-p129/bin/ruby

    Then passenger/rails seems to pick up the correct gems. (mostly, I’m still having issues with mysql)

  26. ChetanAugust 18, 2009 @ 05:15 AM

    If you do ‘install_ruby_186’ then once installed you have to manually download rubygems from http://rubyforge.org/projects/rubygems/ and install it using ruby_186 (use_ruby_186).

  27. justinAugust 20, 2009 @ 07:22 PM

    Anyone get this working with the sqlite3-ruby gem? That’s the last bit for me that is preventing me from running multiple versions side-by-side. The gem installs fine, however, when I try to require it I get an error:

    <internal:gem_prelude>:234:in `push_gem_version_on_load_path’:Gem::LoadError: Could not find RubyGem sqlite3-ruby (>= 0)

    This happens when starting up a Rails app which relies on sqlite3-ruby although the rails app still starts fine after this. I cannot run any tests though.

  28. Jason RudolphAugust 21, 2009 @ 02:45 PM

    @Dan – You don’t want to share your old gems. Just install new gems after switching to the desired Ruby version. “gem install some-gem-name” will just work. And yes, for Rails projects, just “run rake gems:install”.

    @Justin – Which Ruby versions are having issues with the sqlite3-ruby gem?

  29. Aaron evansAugust 25, 2009 @ 03:57 PM

    I thought the only thing needed to switch between ruby versions is just changing an environment variable or two (e.g. RUBY_PATH, RUBY_LIB_PATH) and referencing that in other places (e.g. PATH). The real trick is getting gems and configuring servers.

    What exactly does the Ruby Switcher do different?

  30. Donald DemuthSeptember 04, 2009 @ 01:02 PM

    Thanks, this really helped. Your blog post is actually referenced within a RoR course!