rails.vim, rvm, ZSH, and a curious (infuriating) bug

by gabebw

Updated again on 3/5/2011:Thanks to the RVM website’s vim integration tips, there’s a much simpler fix. Simply put set shell=sh or set shell=bash in your ~/.vimrc, and :!rails console will work. set shell=zsh does NOT work.

Updated 11/8/2010: Thanks to Will for pointing out a mistake I made with login and interactive shells. I’ve fixed the error and added a bit more to clarify the various files each type of shell sources.

I recently ran into an infuriating, apparently nonsensical bit of trickery with RVM, rails.vim, and ZSH. I couldn’t reproduce it with Bash.

A Bit of Background

You can skip this if you want.

  • RVM (Ruby Version Manager) is a command line tool that allows you to switch between Ruby versions very easily. I’m currently using Ruby 1.9.2rc2 with Rails 3.0.0.rc.
  • rails.vim is a fantastic Vim plugin that provides some very nice commands, like :Rmodel <model> (edit app/models/<model>.rb) and :Rscript console (run script/console, or rails console, for Rails 3).
  • you should probably know what Vim is :)
  • ZSH is a shell made by crazy people who want to do way too much with way too many arcane commands. In short, it’s pretty awesome (and if you want to switch it’s mostly compatible with Bash, so your ~/.bashrc might still work if you run chsh -s /bin/zsh)

Please Describe the Night in Question, Sir

I was happily working my way through Michael Hartl’s excellent Rails Tutorial (you really should check it out — I found many gems [god I’m witty] like Object#blank and the annotate-models gem). rails.vim was by my side, I was switching through files like a crazy person, everything was great. Then I run :Rconsole, and this happens:

Loading development environment (Rails 3.0.0.rc)
ruby-1.9.2-rc2 > User.all
/Users/gabe/.rvm/gems/ruby-1.9.2-rc2@rails3/gems/sqlite3-ruby-1.2.5/lib/sqlite3_api.bundle: [BUG] Segmentation fault
ruby 1.8.7 (2009-06-12 patchlevel 174) [universal-darwin10.0]

Emphasis mine. Uhhh, what? I installed sqlite3-ruby like a faithful Rails acolyte (I even used bundler!). Why was rails failing me? Well, first clue: that “Ruby 1.8.7”. Why was vim using my ruby 1.9.2 sqlite3-ruby gem, but giving me a 1.8.7 version?

<2 hours later, after slogging through Google, Ruby forums, and ZSH docs>

The answer: Vim wasn’t sourcing my ~/.zshrc, and therefore not running my RVM scripts, and therefore Ruby 1.8.7 was trying to use the 1.9.2 gem and choking.

Quick fix: source your RVM scripts in your ~/.zshenv:

source "$HOME/.rvm/scripts/rvm"

But why?

Here’s the key: Vim sources dotfiles (~/.zshprofile,  ~/.zshrc) in a different way than the shell itself does. When you open up a terminal, that’s an interactive (and login) shell and so (among other files*), ~/.zshrc is run. But Vim isn’t a login shell. (It isn’t even an interactive shell.)  It doesn’t source ~/.zshrc. Instead, it only sources ~/.zshenv, because everything sources that, not just login shells. For more info, see this section of the ZSH manual.

Note that taking every single RVM reference out of my Bash dotfiles still didn’t make rails.vim choke — not sure what was going on there. I sourced my RVM script in the login shell, then ran Vim, and it didn’t choke.

* It runs ~/.zshenv, ~/.zprofile, ~/.zshrc, and ~/.zlogin (as well as /etc/zshenv, /etc/zprofile etc), but I keep my settings in ~/.zshrc, so that’s the important one for me.