Automatic change RVM environment when switching Git branch

I use RVM all the time when I develop Ruby (and Rails) applications. It’s great for isolating Ruby environments and gem packages for a specific project. I also use git extensively – especially branching when developing new features for an app.

Sometimes a branch works with new gems, that I do not want to pollute my main project-specific gemset with. So I create a new RVM gemset for this particularly branch. This has had its own problems because a “git checkout” now also needed to be followed by a “rvm use” statement. Also having a .ruby-gemset file in the project root led to RVM resetting the current gemset as soon as I changed directory.

One solution could be to check-in the .ruby-version/.ruby-gemset files in each branch, but I don’t want to annoy fellow developers with my RVM files. So I came up with the solution below instead.

First for this example, I assume that you have a git repository containing a master branch and another branch. If not, here’s a quickstart to make this happen:

$ mkdir myproject && cd myproject

$ git init .

$ touch 1.txt

$ git add -A

$ git commit -m 'First master commit'
[master (root-commit) b578056] First master commit
 2 files changed, 2 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 1.txt

$ git checkout -b somebranch
Switched to a new branch 'somebranch'

$ touch 2.txt

$ git add -A

$ git commit -m 'First somebranch commit'
[somebranch d10e2c1] First somebranch commit
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 2.txt

$ git checkout master
Switched to branch 'master'

$ git branch
* master

Okay with that squared away, let’s get on with the actual steps. You need to create a RVM gemset for each branch (master and somebranch) with the appropiate .ruby-version/.ruby-gemset files. The principle is, that you rename them, so they have a postfix named after the branch.

First create for the master branch:

$ rvm --create --ruby-version 2.0.0@myproject-master
ruby-2.0.0-p643 - #gemset created /home/carsten/.rvm/gems/ruby-2.0.0-p643@myproject-master
ruby-2.0.0-p643 - #generating myproject-master wrappers..........

$ ls -a
.  ..  .git  .ruby-gemset  .ruby-version

Then rename the files:

$ mv .ruby-gemset .ruby-gemset-master
$ mv .ruby-version .ruby-version-master

$ ls -a
.  ..  .git  .ruby-gemset-master  .ruby-version-master

Now do the same for the branch “somebranch”:

$ rvm --create --ruby-version 2.0.0@myproject-somebranch
ruby-2.0.0-p643 - #gemset created /home/carsten/.rvm/gems/ruby-2.0.0-p643@myproject-somebranch
ruby-2.0.0-p643 - #generating myproject-somebranch wrappers..........

$ ls -a
.  ..  .git  .ruby-gemset  .ruby-gemset-master  .ruby-version  .ruby-version-master

$ mv .ruby-version .ruby-version-somebranch
$ mv .ruby-gemset .ruby-gemset-somebranch

Since the files are renamed as shown, they will not by themselves trigger an RVM gemset switch, if you enter the directory.

If you look at your git repo now, you will see the files as untracked.

$ git status
On branch master
Untracked files:
  (use "git add ..." to include in what will be committed)


nothing added to commit but untracked files present (use "git add" to track)

As stated in the beginning, we don’t want these files in the repository, so create a .gitignore file and add this:



Now comes the fun part. We are going to make a hook in our git config. Create this file



# Find current branch name
BRANCH=`git rev-parse --abbrev-ref HEAD`

# Copy branch-specific RVM files, if available - default to master-branch
if [ -f .ruby-gemset-$BRANCH ];
  cp -f .ruby-gemset-$BRANCH .ruby-gemset
  cp -f .ruby-gemset-master .ruby-gemset

if [ -f .ruby-version-$BRANCH ];
  cp -f .ruby-version-$BRANCH .ruby-version
  cp -f .ruby-version-master .ruby-version

And make sure, that the file is executable, since it is just a script:

chmod +x .git/hooks/post-checkout

After you have done this, everytime you checkout a branch, this script will be called. If you checkout somebranch, it will look for a .ruby-version-somebranch and .ruby-gemset-somebranch and copy them to .ruby-version and .ruby-gemset respectively. If you create a new branch but do not make a specific gemset for this branch, the script will instead copy .ruby-version-master/.ruby-gemset-master. So always as a minimum create these.

You might think that now you a all done. However if you try to checkout a “somebranch” now, things will seem strange. The .ruby-gemset file will be an exact copy of .ruby-gemset-somebranch, but if you call “rvm current”, you will still be on the master gemset. Why is this so?

The thing is: .ruby-gemset is now placed correctly, but will not be read by RVM until you change into the actual directory. Try this:

$ git checkout somebranch 
Switched to branch 'somebranch'

$ rvm current
ruby-2.0.0-p643@myproject-master      <== Not what we expected

$ cd .

$ rvm current
ruby-2.0.0-p643@myproject-somebranch  <== Much better

But this is still an extra manual step, that complicates things. You WILL forget this at some point, so let's get rid of it.

You need to edit your $HOME/.bashrc file and add this line:


git () { /usr/bin/git "$@"; cd .; }

This changes the git command to a function, which calls the executable git in /usr/bin with all arguments, and afterwards does the otherwise harmless "cd ." which will then make RVM reload the .ruby-version/.ruby-gemset files.

Exit the shell and open a new to reload .bashrc, and you're good to go.

Please let me know, if you have any trouble with the above. Everything has been tested, but evil typos may have creeped into the text.

Have fun!

Trouble with Net::HTTP in Ruby 1.8.7 (released with Ubuntu 10.04)

I stumbled upon an error trying to work with acts_as_solr just after upgrading to Ubuntu 10.04. When trying to start the solr-daemon with

rake solr:start

i suddenly got an error not seen before:

undefined method `closed?' for nil:NilClass
/usr/lib/ruby/1.8/net/http.rb:1060:in `request'
/usr/lib/ruby/1.8/net/http.rb:962:in `request_head'

As the error hints, it’s something to do with the net/http library. After some googling I found out, that it is because Ubuntu 10.04 ships with Ruby 1.8.7, and that this particular version has a bug in the net/http library. Here’s the bug-report and the patch that will help:

Hopefully this patch will soon find its way to Canonical’s updates.

The woes of libodbc-ruby1.8 and Debian + Ubuntu

Update 05-05-2010: This issue still exists on the new Ubuntu 10.04 LTS (Lucid Lynx). The dist-upgrade will override any version locks that you have made on libodbc-ruby1.8 and install version 0.9997-2 (and lock it). So after a dist-upgrade you will have to remove libodbc-ruby1.8 and install the older version again.

I have the dubious honor of developing on a Rails application, that runs on top of Microsoft SQL Server. This has given some headaches at our most recent system upgrades.

My development machine runs Ubuntu 9.10 (Karmic Koala). Our servers run Debian 5.0 (Lenny).

If you run any of these OS versions and encounter an error like the following:

dbd-odbc-0.2.4/lib/dbd/odbc/driver.rb:36:in `connect':DBI::DatabaseError: INTERN (0) [RubyODBC]Cannot allocate SQLHENV

then help can be found here.

The problem on both OS’es lies in the package libodbc-ruby1.8. But it is actually stranger than you might expect, which I will explain below.

Ubuntu first

We’ll start off with Ubuntu. Fire up Synaptic Package Manger and search for libodbc-ruby1.8. You will see, that the distribution package is versioned 0.9997-2. You need to uninstall this and install version 0.9995-1 instead. You can download version 0.9995-1 here:

Now install it with apt-get and… problem solved. Please note however that your automatic package update will revert to version 0.9997-2 unless you uncheck it before running the update.

Update 19-02-2010: This is also an issue on the 64-bit version of Ubuntu 9.10. Here’s a link where you can download the 0.9995-1 .deb package for both 32-bit AND 64-bit. Thanks Goran.

Debian next

On Debian it’s the other way around. Debian comes installed with libodbc-ruby1.8 version 0.9995-1 and you need to upgrade this to 0.9997-2. This package is currently only found in unstable, but you can download it here:

Install it with apt-get, overriding the previous package.

Hope this saves you from the days of work that I invested in this particular oddity. :-)

Thinking about searching in your app?

I’ll cut to the chase. There is really only one good search engine for Rails applications at the moment of this writing.

It’s called ThinkingSphinx, it’s fast, it’s reliable, and it has the easiest Rails implementation, that I have seen so far.

There is really no need for me to do a tutorial here, since Pat Allan has already done a great one himself. Read it here.

I use ThinkingSphinx in production on my Gipote site. Before that I’ve been with Ferret (not good in a multi-mongrel production site), and UltraSphinx (gave me great problems when indexing multiple models). After using ThinkingSphinx as my search engine, all pain has gone.

Hooray – now full-time on Rails

I have decided to sell my company and get a job at a company developing solely in Ruby on Rails.

This is really the best decision, that I’ve done for myself AND my family for a very long time. The career as self-employed was really starting to tear me down.

So now – almost 2 years since I complained about the desire to work only with Rails but having the economical need to do PHP – I have finally shedded the PHP load and am now a full-time Rails developer.

Dear PHP: Thank you for 9 great years. It has been fun, but now I really must move on.

At the same time, I decided to change the name of my blog. I will be having a lot of travelling by train each day, and although I will do a lot of coding on these trips, it is also a perfect place, to write down the thoughts and ideas coming up during the day.

Tabs be damned

– at least that seems to be a clear oppinion of the Rails community.

Okay so I lied to you in the last post. I’ve been working on my first real Rails project for quite some time now, so instead of a realtime diary, I will be reflecting upon the major issues, that I went through (eg. “how to make a multiple-page wizard-like create controller”). The reason being, that I haven’t been allowed to speak in public about the project until now – we will release it in the coming week.

But I will break the cronology by starting with one of my latest issues:

Ruby on Rails does not allow tab characters for indentation in RHTML templates

Have you ever tried to get a wierd “SyntaxError Exception” when calling a page in your Rails application? There is nothing wrong with the inlined Ruby code.

It turns out, that if you indent your RHTML code with tab characters instead of spaces, the ActionViewer will report a compile error when evaluating your template.

I know, accept, and also appreciate, that Rails is “oppinionated” software. But this is really ridiculous. IMHO tabs are the only way to go – combined of course with spaces for alignment.

This has been an issue at least since Rails 1.1 (I haven’t been on Rails before that), and I found somebody mentioning a workaround then.

So I patched Rails and worked happily ever after – that is until yesterday, when I decided I wanted to release the app with Rails 1.2 instead of 1.1 (better to work out the knots before going live).

I was slammed with RHTML Syntax Errors again. And I had completely forgotten about this little patch, which was, of course, now overruled by the new version of Rails.

It turned out (after much debugging), that the ActionView has been recoded quite a lot, so the previous patch could not be applied in the same place.

But here is what you should do:

1) In Ruby’s lib folder, find the file:

2) From line 504:

def compile_template(extension, template, file_name, local_assigns)
render_symbol = assign_method_name(extension, template, file_name)
render_source = create_template_source(extension, template, render_symbol, local_assigns.keys)

add these two lines just in the top of the method:

def compile_template(extension, template, file_name, local_assigns)
# convert all tab-characters to space-indentation (4 spaces)
template = template.gsub(/t/, ” “) unless template.nil?

render_symbol = assign_method_name(extension, template, file_name)
render_source = create_template_source(extension, template, render_symbol, local_assigns.keys)

Now I only need to find out, how I can format my code in Blogger… 😉

Why I must use Rails but cannot abandon PHP

I think I’m an ordinary guy.

At least in programming terms, I’m pretty ordinary. Over the last year, a lot of people have been talking about, how they would like to switch permanently to Ruby on Rails, but they can still only use it for spare-time projects, since their company/customers/etc. are very deep into PHP/.NET/J2EE/whatever technology in existing projects.

I definetely fall into this category, which then – through the philosophy that “ordinary” is made up by the most people – makes me just like everyone else.

I have my own programming company in Denmark. We used to call ourselves a “webbureau”, but skipped the last part, since now only 20% of our projects are plain homepages with or without a CMS. The rest are real application-programming, although mostly with a webbased interface.

Most of our projects are developed in PHP. That means we have a lot of finished solutions for our customers in PHP, which again explains why it will be quite costly to abandon this language alltogether. Besides, I’ve come to like PHP, since it saved me from the IMHO hideous ASP/VBScript, that I used before (we’re back in ’98).

I’ve been a long way around. As a genuine C/C++ hacker, I’ve always had this urge to experiment with (for me) new things. This have included (in the past) Delphi, Java, and lately for web-development: Perl and Python (and some of its web-frameworks, inclding Zope and ). But always seeking back to PHP when it came to web-development. And my customerbase grew, and so did the software made in PHP.

So now when I’ve found Rails, I am in a position where I simply cannot just switch away from PHP, although I sure would like to. Rails is simply geniously made.

But I have just started a “spare-time” project, which I am making in Rails. And I will try to use this blog as a diary for this project. In the hope, that others (if any are listening) can learn from my mistakes.