Untangling RVM and Bundler, for the novice

I was introduced to the combination of RVM and Bundler while working with my friend James on a project earlier in the year. It’s a nice combination of Ruby tools which offers developers a way to keep tabs on the Ruby gems they are using in a project and to avoid conflicts, or the accidental use of other versions of those gems, when they are actively developing or deploying their work. Typically these projects might be Ruby on Rails-based web applications but although ‘Rails’ is often accidentally substituted for ‘Ruby’ there is no reason why Bundler + RVM should be any less useful outside of Rails.

I found the post he pointed out, by Mike Lindsaar, very helpful to keep me enthused and get me trying things out but I also found the concept was still hard to grasp. Although both Bundler and RVM are adequately documented, somehow their example-driven documentation doesn’t quite make things clear at first/second reading. So here’s a quick synopsis which I’ve written to help my own understanding.

RVM

RVM (Ruby Version Manager) is a tool that creates named Ruby builds and named sets of gems. It lets you swap between these builds and sets at will.

Use RVM to build a named Ruby, then use RVM commands to modify the environment in your current shell so it will use that build instead of the system default. Likewise, once you have created a named gemset with RVM, you can then use RVM commands to bring the gems in that gemset into use in your shell. They will be made available to whichever Ruby is currently accessible using the information in your environment.

An .rvmrc file lets RVM automatically switch the Ruby build and gemset without human intervention.

Bundler

Bundler is a gem that installs and uninstalls other gems following a list you maintain.

The list centralises the information about which gems are needed to allow a given project’s Ruby code to run. It tidies up some loose ends and hard-to-manage conflicts by allowing you to specify exactly which gem version is needed to run the code, so that if there’s a feature that is missing from earlier gem versions or removed from later ones you can keep using the version you need even when it is obsolete.

The Gemfile, the list that Bundler works with, is plaintext and therefore version-controllable. It sits naturally at the root of the project.

Putting them together

RVM is great on its own, because as you swap between projects in daily work on your own machine you can swap between different Ruby versions and different sets of gems instantly. You are protected from updates to a gem on the system breaking things in your projects and you can retrospectively introduce an RVM gemset to sort things out if that does happen. That should make it really useful for anyone developing gems or dealing with legacy code issues.

The Bundler gem is required by Rails 3 itself [‘baked in’ as I am sure its developers would say, with tongues in their cheeks], and I guess that’s because it was the Rails use-case itself that caused Bundler to be written. So either tool is useful alone. The point of Mike’s post is that by coupling the two together you get a really nice combination. Here’s what you can do.

  1. RVM to create a named Ruby build, if desired

  2. RVM to create a named gemset (probably named for the project)

  3. .rvmrc file in project root to ensure that when code is executed in the project’s directory tree it’s run with the right Ruby and gemset

  4. Gemfile in project root to specify gems required for the codebase (remember this is version-controllable)

  5. Bundler to read the list of gems and install them; the gems are installed within the environment that’s active, so they’ll be installed within the RVM gemset for the project and not elsewhere

Of course to benefit from all this on your own machine with multiple projects is one thing; RVM will not seem nearly as necessary if the project code is deployed to a dedicated server with no other web applications running on it. But not all deployments look like that.

I think I have this all right; comments welcome of course.

Published on 11/07/2010 at 13:28 by Technophile, tags , , , ,

Ruby Mendicant University

I came across this post about Ruby Mendicant University while reading up on Prawn, a Ruby PDF generation library. RMU is an interesting idea in its own right – is it a new idea? – but what I liked about the post, what connected with me, was the discussion of the ‘plateau’ of learning that comes after grasping the basics of the language, when the need is to discover about good style and efficient, elegant coding. That’s something very familiar.

There are a lot of people who have gone through the initial gauntlet only to plateau and find that while they can play by ear, they can’t quite read the music

Because I often work alone and I have to somehow solve the problems I take on I am slowly grinding away at my Ruby ignorance. It’s great to find neat and expressive ways to achieve things, and it’s always depressing to leave a trail of ugly-looking code in one’s wake, so there are sticks as well as carrots. But as the interviewer prompts, ‘Underwear + ??? = Ruby Knowledge. Meaning, there’s bloody nothing in the middle range.’ In other words, there’s a deafening internet silence just at the point when guidance could be most valuable. This stage includes all sorts of really interesting things, things I know I want to know about but which are nevertheless frustratingly unknown unknowns.

My previous post perhaps illustrates the rather unfocused understanding I have gained so far; I wasn’t able to make the correct assumption about the precedence of the operators because I wasn’t taking into account the = operator in the statement. Un-fluent thinking.

I would guess that in a team with a strong leader, or with a mentor, this stage can be crossed pretty fast. But for those people who are more isolated, the idea of focused group learning online, via IRC, sounds smart. And it looks to be a success so far.

Published on 24/06/2010 at 09:01 by Technophile, tags , , , ,

Ruby or and || operator evaluation

I wanted to define a variable in a way that allowed it either to be the result of a method or, if that method didn’t produce anything, a preset default value.

The method was written so that it would return nothing if a certain condition was not met. Here’s my experimental version:

def foo(argument) if argument.class == “”.class

return argument

end end

foo(“bar”) => “bar”

foo(123) => nil

</typo:code>

Then I tested to see what happened if I wrote an expression to evaluate the output. I used the ‘or’ operator. It behaved as expected:

foo(“bar”) or “Nope!” => “bar”

foo(123) or “Nope!” => “Nope!”</typo:code>

But although when calling experimental method it does not seem to matter what kind of object is given on the right hand side of the evaluation…

foo(“bar”) or {“test”=>1, “me”=>2} => “bar”

foo(123) or {“test”=>1, “me”=>2} => {“me”=>2, “test”=>1}</typo:code>

… a similarly written expression in the real script would receive nil from a method, yet that returned value of nil would be chosen in preference to the object on the right hand side. Effectively:

foo(123) or {“test”=>1, “me”=>2} => nil</typo:code>

I changed the evaluation operator from ‘or’ to ‘||’, and it worked nicely, effectively:

foo(123) || {“test”=>1, “me”=>2} => {“me”=>2, “test”=>1}</typo:code>

Here is Programming Ruby 1/e on the or and || operators:

… both “or” and “||” evaluate to true if either operand is true. They evaluate their second operand only if the first is false. As with “and”, the only difference between “or” and “||” is their precedence.

http://ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html#S1

Published on 23/06/2010 at 15:34 by Technophile, tags , , , ,

Powered by Publify – Thème Frédéric de Villamil | Photo Glenn