Rails 1.2.x + Ruby 1.8.6 + Snow Leopard: the missing link


Yesterday, I migrated to Snow Leopard.  After a day of file transfers, disk formatting, apps installation, password and license keys recovery, I finally was ready to install the Rails stack.  It’s great to do a clean install, we can get rid of the crap that was installed in the last 2 years.

Today, I spent a few hours on the Rails stack.  And I ran into some problems that I need to share with you because I didn’t find an answer on the net.

Background

I had to install the Rails stack, the framework I use in most (if not all) my projects.  The challenge was that I still have a few Rails projects that run under 1.2.x.  And Rails 1.2.x is not a good friend of Ruby 1.8.7, the version of ruby that ships with Snow Leopard.

Back on Tiger, I was using the amazing Locomotive application, which was a way to have dedicated environments for rails applications.  Then, when I moved to Leopard, Locomotive was not supported and I had to deal with all the apps sharing the same gems, same ruby and same everything.  Fortunately, ruby 1.8.6 was handling my Rails 1.2.x projects properly. I was also unsing Capistrano 1.4.2 along side 2.5.2 to deploy those old projects (i.e. cap _1.4.2_ deploy_with_migrations).

Now on Snow Leopard, I wanted to keep this flexibility.  I looked at different ways to set-up Rails on my Macbook Pro (Core 2 Duo).  The one on the Rails wiki was interesting, and I was used to this set-up, but I wanted to do a bit more.  I remembered that a new package manager was borned this year: homebrew.  I heard some good things about it.  And my last wish was to have multiple versions of Ruby on my system. This guide was a really good “instructor” on using RVM, the Ruby Version Manager.  Using RVM, you can have ruby 1.8.6, 1.8.7, 1.9.1 and even jruby and ree (Ruby Enterprise Edition).  This is cool, I will finally have a chance to start testing with 1.9.1 and eventually start new projects with it.

So I installed all that using my own recipee (which follows next), and everything was working fine with Ruby 1.8.7 and Rails 2.3.5.  When I started to use Ruby 1.8.6, my rails apps were hanging so bad, I was forced to “kill -9″ the processes (CTRL-C was not working).  Anytime the Rails environment was loading, the process would hang.

After a few hours of investigation, I found out that the problem was with RMagick.  And the problem was due to the use of NSLinkModule functions in dln.c (ruby 1.8.6 source code). Thanks to RVM, we have access to the source code of ruby. After applying a patch to ruby 1.8.6, as described in the bug report, everything started to work.

So here we go, follow me through the installation of the Rails stack on Snow Leopard.

Note 1: I did a clean install of Snow Leopard.  Not sure that my recipe will work on a Snow Leopard migration.  It might, but you will have to reinstall some 32-bit gems that compile some binary stuff.

Note 2: I’m using Textmate.  If you are using Aptana, you might want to check on the web, I think I’ve seen some blogs describing some issues with RVM and Aptana.  According to this post, starting Aptana from the command line makes it use the RVM interpreter.

Note 3: Phusion Passenger is awesome.  But in the past, I tried using it on my development machine and I didn’t like it so much.  I still prefer starting the server myself and see the output in my terminal window.  RMV supports Passenger, but I didn’t play with it.

Prerequisites

  • If you are still on Leopard, prior to migrate to Snow Leopard, find an empty drive and use SuperDuper to clone your hard drive.  This is an excellent backup solution (you can boot from the backup drive).
  • Format your drive and installer Snow Leopard.
  • Get the latest version of XCode on the Apple Developer Site and install it.

Homebrew

We could use MacPorts, but Homebrew takes less space (it uses what we already have on Mac OS X) and it does not require being root.  And Ryan Bates recommends it.

As mentioned on Homebrew’s wiki, you can install it anywhere, but lots of 3rd party solutions expect to have things in /usr/local. And Homebrew’s files are well isolated and the uninstall is well documented.  So there is no danger installing it under /usr/local.

So let’s change the owner of the /usr/local folder (otherwise, we always have to switch to super user).  I know, this is not standard practice, but hey, we’re on a mac and most likely you will be the only one using stuff in /usr/local.

sudo chown -R `whoami` /usr/local

Then, let’s install Homebrew (just one line, isn’t that great?).

curl -L http://github.com/mxcl/homebrew/tarball/master | tar xz --strip 1 -C /usr/local

Basic packages

Now let’s install some basic packages that we all love and cherish.

brew install readline
brew install git
brew install wget
brew install imagemagick

You have to agree that this is cool.  No sources to download and untar, no configure to run, … Homebrew takes care of doing all that.  Of course, we don’t have as much control, but this is fine with me so far.

MySQL

I’m still using MySQL (although Postgresql is on my R&D to-do list for 2010).  It’s installation is well documented.  You can download a disk image from the MySQL web site or compile the source code, or simply use Homebrew:

brew install mysql
mysql_install_db
sudo chown `whoami` /var/mysql

I also like to apply some changes to the default configuration. Here’s my /etc/my.cnf file:

[mysqld]
#Max packetlength to send/receive from to server.
max_allowed_packet=64M
socket = /var/mysql/mysql.sock
character-set-server = utf8
default-character-set = utf8

#This option makes InnoDB to store each created table into its own .ibd file.
innodb_file_per_table

[mysql]
default-character-set = utf8

[client]
socket = /var/mysql/mysql.sock
default-character-set = utf8

Then, let’s start the server and also install the launcher.

cd /usr/local/Cellar/mysql/5.1.41; /usr/local/Cellar/mysql/5.1.41/bin/mysqld_safe &
launchctl load -w /usr/local/Cellar/mysql/5.1.41/com.mysql.mysqld.plist

Ruby Version Manager (RVM)

Now that we have the foundation installed, let’s implement the Ruby Version Manager.  RVM keeps multiple ruby environments isolated from each other.  Each one has its own ruby version (compiled from source) and its own gems (which is awesome).

So instead of using the Snow Leopard out-of-the-box Ruby , let’s set-up an environment for 1.8.7.

But first, let’s install RVM (replace USER with your username):

gem install rvm
echo "if [[ -s /Users/USER/.rvm/scripts/rvm ]] ; then source /Users/USER/.rvm/scripts/rvm ; fi" >> ~/.bash_login
rvm install 1.8.7
rvm use 1.8.7

This will install everything in the .rvm folder in your home. If you change your mind later, it’s easy to uninstall: rvm implode.

You can confirm the installation by running rvm list.

Gems

RVM will install a version of Rubygems for each environment, with the proper gem sources (yes, gemcutter is already in the list). We have to install all the gems we need for each environment. Let’s install the common ones:

gem install ruby-debug
gem install capistrano
gem install rmagick
gem install sqlite3-ruby
gem install mongrel
export ARCHFLAGS="-arch i386 -arch x86_64"
gem install mysql -- --with-mysql-dir=/usr/local --with-mysql-config=/usr/local/bin/mysql_config
gem install rails
gem install manalang-bdoc

Now, to really see the power of isolated environments, launch bdoc from the command line.  See? Only the gems that we just installed.

Then, you can install additional gems, or go into one of your Rails 2.x project and issue rake gems:install.

Ruby 1.8.6

Now that we have ruby 1.8.7 working, let’s install version 1.8.6 so that we can do maintenance in our old Rails projects running under 1.2.1. And let’s make 1.8.7 the default interpreter when we open a new bash session.

rvm install 1.8.6
rvm 1.8.7 --default
rvm use 1.8.6

Now, we have to install a backport from ruby 1.8.7 (patch) so that we can use RMagick under ruby 1.8.6 on Snow Leopard. I suspect that it also fixes some other weird bugs.

rvm use 1.8.6
cd ~/.rvm/src/ruby-1.8.6-p383
wget http://redmine.ruby-lang.org/attachments/download/580 -O dln.patch
patch dln.c dln.patch
make
make install

Finally, let’s install the gems that we need.

gem install ruby-debug
gem install capistrano -v 1.4.2
gem install rmagick
gem install mongrel
export ARCHFLAGS="-arch i386 -arch x86_64"
gem install mysql -- --with-mysql-dir=/usr/local --with-mysql-config=/usr/local/bin/mysql_config
gem install rails -v 1.2.1
gem install manalang-bdoc

And that’s it. We now have 2 isolated interpreters and their gems. We are now in business for eventually migrating some projects to ruby 1.9.

Candies

There is a way with RVM to automatically switch interpreter when you cd to a project’s folder.  Simply provide a .rvmrc file in the project’s folder:

echo "rvm 1.8.6%projecta" > ~/projects/projecta/.rvmrc

Also handy is to have the current interpreter displayed in the command line prompt. Simply edit your ~/.bash_login file and add the following line:

export PS1="\$(~/.rvm/bin/rvm-prompt) $PS1"

Have fun, and continue to enjoy Ruby on Rails.

7 thoughts on “Rails 1.2.x + Ruby 1.8.6 + Snow Leopard: the missing link

  1. Pingback: Setting Up mysql as utf8 for Ruby on Rails using homebrew | Nobody Listens Anyway

  2. Hi, i am listening :). What happen if i install locomotive in snow leopard anyway. it will work?. Please help me if this piss me off to much i am considering moving to windows and instant rails :)

    • Locomotive was supported up to Tiger. When I moved to Leopard, I had to use what comes with Mac OS X instead of Locomotive. It was not that bad because Leopard was providing ruby 1.8.6. Snow Leopard comes with ruby 1.8.7. So all my legacy projects that runs under ruby 1.8.6 needed a sandbox, and RVM solved the issue for me.

      If you are about to start brand new projects, you might as well use the out-of-the-box ruby from Snow Leopard. But if you are going to do serious development, you should install RVM. It is pretty easy to install and you will be able to create isolated sandboxes for different projects. The guy who is behind RVM got a Ruby Hero award last week at RailsConf, so the community really backs this tool. If you move to Windows an existing project, depending on the external dependencies, you might experience some problems.

  3. Hi hugofrappier,

    what a sweet post! It is the sharing by people like you that make people like me survive in this game :) Thanks abunch!

    my 2cents (running Snow Leopard and latest Xcode):
    Under RVM I needed to add

    # rvm package install readline
    # rvm install 1.8.7 -C –with-readline-dir=$HOME/.rvm/usr

    (and again under Ruby 1.8.6)

    Under Gems I had to add
    # gem sources -a http://gems.github.com

    Except for these couple of hickups, this was one very joyful walk in the park – thanks to you!

    (BTW: I’ll report another small ‘show-stopper’ to Homebrew – when doing ‘brew install imagemagick’ I was meat with “curl: (78) RETR response: 550″ which turned out to be an issue with the version – ImageMagick-6.6.3-6.tar.bz2 is the version to use)

    Again, Hugo, thank you for taking the time to document your findings!

    Cheers,
    Walther

  4. Pingback: Getting snow on the Leopard « The Web Appliances Crest

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s