This is a guest post by my friend Ivan Stroganov, a fellow Ruby on Rails developer attending Dev Bootcamp with me. You can read more from Ivan on his blog and check out his projects on Github.
I’ll start from afar. One thing that seemed like absolute magic as a Ruby beginner was the whole “gem install …” process. Now I have a little better idea, and RVM really brings it together. Here’s how:
When you do “gem install x” in your terminal, the terminal connects to the server (specified in your config file), downloads the gem and installs it by default to the /usr/local/lib/ruby directory. This makes it available to the ruby version installed on your computer.
However, doing it just like that can become problematic.
What is rvm (Ruby Version Manager)?
Broadly, it allows you to have several versions of ruby installed on the same computer without conflicts. There are other tools that also accomplish that task (rbenv for example). If you use rvm – check this out in your command line:
$ rvm list
That will give you a list of ruby versions installed, with current version one pointed out with =* or =>. Pretty nifty, huh?
What’s different about RVM?
It creates a separate gem library for each ruby version. More then that, it allows you to create separate libraries for each new project.
Note: It can be argued that having separate libraries is redundant and it creates more clutter then benefit… but there are also haters who curse at TDD or OO design… Bottom line is, RVM is just a tool with extensive functionality, and nobody is making you use it to it’s full potential if you don’t want to. If you REALLY DON’T WANT TO HAVE some of it’s features, then certainly you can find a different tool with functionality that suits your desires better.
Back to magic: so now suddenly you have those separate libraries. What about the gems? where do they get installed now? if you type
$ rvm gemset list
it will list the gemsets (libraries of gems) for your current version, and also tell you where they live (by default in Users/your_name/.rvm/gems/your_ruby_version). You can go check out “.rvm” folder in your finder or terminal to see what else is in there.
So basically when you just do “gem install x”, it will install it into the folder dedicated to this particular ruby version. Already better, but still not great. The safest way is to keep the gems for each project separate (some might argue that repetitive installation of the same gems is redundant, but come on – gems are usually about 1-2mb in size, many much smaller – so the small waste of space is totally worth keeping eggs in separate baskets).
You might say “Keeping libraries for projects sounds good in theory, but wait, doesn’t “rails new my_app” run bundle install already when it runs? So it will keep dropping all the gems into the main library anyway.” Have no fear – there’s a simple solution: add the flag ‘–skip-bundle’ to your rails configuration like this:
$ echo --skip-bundle > ~/.railsrc
You’re all set – ‘rails new my_app’ will NOT run bundle install any more.
Now, here’s your workflow in 4 simple steps:
$ rails new my_awesome_app #notice how quick (near instant) it is with no 'bundle install' at the end $ cd my_awesome_app $ rvm --create --rvmrc 1.9.3@my_awesome_app #this creates a "gemset" - basically just a folder in your ~/.rvm folder to keep your gems for this particular project, and a configuration file .rvmrc that instructs rvm to look for gems in that dedicated folder $ bundle #exactly the same as bundle install, but one word shorter - but you MUST do it, because it didn't do it for you when you ran 'rails new'
That’s it. Pat yourself on the back, you’re ready to go build your kickass awesome app with no fear of any unpredictable gem conflicts.
You might ask – what about all those gems that are already in my ‘global’ library for the ruby version? Why do I need to keep them? What about all the projects I already have that have gems who knows where? Is it too late to get a separate basket for those eggs?
On one hand – so far it works – so no real need to worry about possible conflicts if you start using rvm properly from now on… but if you’re feel a little obsessive-compulsive about keeping your system tidy – here’s some magic for you:
$gem list | cut -d" " -f1 | xargs gem uninstall -aIx
This will uninstall ALL your gems for your current ruby version. It will probably clear up about 150ish mb of space… But more importantly it will give you peace of mind that things are tidy .
Do remember – you need to run ‘bundle’ in all your existing projects in which don’t have their own gemset yet (but now you know to run ‘rvm –create –rvmrc your_ruby_version@your_project_name’ before running ‘bundle’, right?)
If something I wrote here is not quite right or plain wrong, do enlighten me please!