

Rubies and Bundles - switching from RVM to rbenv - hcm
http://hmarr.com/2012/nov/08/rubies-and-bundles/

======
bradleyland
Why manage something manually when there are good tools to abstract it away in
to the background? That's kind of the feeling I get when using rbenv +
bundler.

Let me predicate this by pointing out that I manage a lot of Ruby projects
(many are old) that require a wide variety of Ruby and gem versions. Obviously
my solution isn't the best for everyone. Some developers will never have to
worry about conflicting gem versions, because they work primarily on one
project with one set of dependencies. The incremental value of the items I'm
about to point out don't represent significant value to them. Enough with the
disclaimers.

Bundler has the ability to alter your Ruby env variables so that you can
easily install and execute gems from any location. This is the feature that
allows you to use completely different gems across many projects without any
conflicts. As the author suggests, you can pass a path at the time you invoke
`bundle install` as a means to specify this location. This allows you to
segregate gems to avoid conflicts. The author also points out that the trade-
off is "one annoying side effect: any binaries that are installed (e.g. rspec,
foreman, cap) are no longer available in your shell’s path". Bummer. I wonder
if there's a way around that? Hey, we could manage our environment so that
these items are in our path, but remain segregated. We could even write some
tidy scripts that automate it for us. Enter RVM.

This is why I don't understand the drive to move to rbenv for developers who
need these features. I use RVM _and_ bundler all the time. RVM doesn't
preclude the use of bundler, and bundler doesn't make RVM obsolete. When I
establish an RVM gemset and .rvmrc, I've abstracted away all the '--
path=./.somebundledir' and `bundle exec` nonsense. I only think about it once,
then I'm free to use the tools without additional cruft. I'm probably happier
than I should be that I can type `cap staging deploy:pending` instead of
`bundle exec cap staging deploy:pending`.

If you don't need gemsets, or you're only managing a very small number of Ruby
projects, I suppose I can understand wanting a simpler tool, but I don't find
RVM terribly complex. A lot of people will say "choice is good", but principle
applied without cause isn't good, it's just pedantic.

~~~
hcm
Perhaps it wasn't clear enough, but the post pointed out that typing 'bundle
exec' and explicitly using --path isn't necessary. Once you've added one item
to your PATH, and two lines to your bundler config file, you don't need to
think about it ever again, it just works. If you want all your gems in one
place, simply remove the BUNDLE_PATH line and change the BUNDLE_BIN directory
to whatever you want (presumably something within your home directory).

I don't want to get in to the rbenv vs RVM debate - they're both good tools
and it's an issue that has been done to death. I linked to five articles in
the post, and you can find many, many more with a simple Google. My personal
motivation for switching was that bundler's overridden 'cd' function includes
some commands that fail, which is fine under most circumstances but it breaks
as soon as you use 'set -e' in bash. We spoke to the author and he said he
said that RVM wouldn't be 'set -e' compatible in the foreseeable future.

~~~
bradleyland
To be clear, my goal is not to sway your decision, but to provide an informed
discussion for those making the evaluation. Whether we want it to be, it is an
rbenv vs RVM debate, because those are the tools we're evaluating.

My observation is that rbenv users often tack on additional ad hoc solutions
to arrive at the same convenience provided by RVM. The primary objection I
hear to RVM is the `cd` override, which is optional.

------
masnick
I've never found it necessary to use the --path or --binatubs options with
rbenv.

For --path, I just use the default which presumably puts everything in the
main rbenv folder for gems. I've never had a problem with this.

For the problem of having to type "bundle exec" before every command that uses
a binary from a gem, I've heard of two alternative solutions. One is aliasing
"bundle exec" to "be" or something to make it quicker to type. The other is
using zsh/oh-my-zsh instead of bash and using a plugin (can't remember the
name off the top of my head) that automatically figures out what should be
bundle execed and takes care of it behind the scenes. I've never had trouble
with this either.

~~~
hcm
The issue with not using --path is that gems will leak between different
projects, so you'll probably run in to trouble when projects depend on
different versions of the same gem.

I've also used shell plugins to remedy the bundle exec issue, but they've
often caused more problems than they solve. I'd much rather just stick
something in my PATH than use shell plugins.

~~~
elektronaut
I find it much easier to simply explicitly require a specific version in my
Gemfile if I'm having trouble with a gem, rather than having the extra
overhead of managing multiple sets of gems.

I think it's a more correct solution as well. You won't have any guarantees
that Bundler will resolve the dependencies correctly in production when it
doesn't in your development environment.

~~~
hcm
That's also a good approach. The moving the bundler binstubs to a central
location would work nicely as well, I imagine.

~~~
elektronaut
Absolutely.

I'm using oh-my-zsh with the bundler plugin, which aliases all binstubs to a
function that prepends bundle exec if there's a Gemfile. It works very well in
practice. rbenv handles the correct ruby version, Bundler loads the right gem,
and it all falls back to the newest version on the system default ruby.

It's a few more moving parts behind the scenes than I'd prefer, but once
configured it's completely transparent.

------
darrencauthon
Sometimes the simpler solution is the more complex tool -- if that's what
everybody already uses and if it already works. Just like RVM.

~~~
mattdeboard
If the python community felt this way we'd all still be using easy_install and
installing our libraries at system root.

~~~
darrencauthon
I'm not saying it's always the rule. It depends on the context. If the context
is a group of Ruby/Rails devs who are efficiently building applications in
exchange for money, and the new(er) tool is one that:

1.) Ends with the same net result for the developer, and 2.) Adds a little bit
of complexity on setup and rules around use, then

why switch? I'm perfectly willing to trade up my development tools, but I want
a better net gain before I switch.

Perhaps that net gain will be to keep up with a growing number of devs who use
it? We'll see.

~~~
dlisboa
You can use the right tools in the wrong way and be productive. You're still
using them wrong. Most people use Bundler and RVM gemsets in a way that
Bundler wouldn't even be needed. Rbenv forces you to learn the proper way of
project management and it actually reduces complexity once people get over the
small learning curve of using the correct tools for each thing. Bundler
manages dependency, Rbenv just switches rubies. RVM adds so much more that it
blurs the lines between things.

~~~
bradleyland
> Rbenv forces you to learn the proper way of project management and it
> actually reduces complexity once people get over the small learning curve of
> using the correct tools for each thing.

Boy did you overreach on this one. What about rbenv constitutes the "proper
way" versus a tool like RVM? If the argument is that RVM abstracts away too
much of the underpinnings, then you've just a made a philosophical argument
that is in conflict with much of the work that we do as developers.

RVM is simply an environment manager. One should always understand the
environment that they're managing, but using tools to increase the efficiency
of that management is not in violation of the "proper way". If abstraction of
underlying complexity is bad, we shouldn't be using bundler, rbenv, or even
init scripts and package managers. We should start all system processes with
the direct invocation and build and install software by hand, lest we not
learn the "proper way".

If we accept that abstraction is not necessarily a bad thing, then we can
recognize that there's nothing about rbenv that is any more "proper" than RVM,
and we can all use the tools we prefer.

I prefer not to have to append '--path=./somedir' every time I run `bundle
install`.

I prefer not to have to prepend 'bundle exec' to every shell tool in my
toolchain.

I prefer to have all my rubies and gemsets organized in a single location
instead of spread out across my projects.

I understand that by using RVM a background process is altering my
environment. I also know how to run `rvm info`, read the output, and
understand the terms.

Those are my preferences. They're no more right (or wrong) than yours.

------
zimbatm
Just a little plug, I wrote this language-agnostic environment loader:
<http://direnv.net> . Unline rvm it doesn't hijack all your shell builtins and
is very lightweigh (keeps your prompt fast). I use it every day load load
ruby/python/go/... projects in isolation.

------
llasram
For something even simpler, check out redenv --
<https://github.com/damballa/redenv> . It tries to provide something which
works more like Python's virtualenv, just doing the minimum necessary to setup
an environment referencing a particular system-provided Ruby installation, but
with an isolated gemset.

------
hayksaakian
In one of the linked posts they compare it to the rails vs Sinatra
relationship, but in this case, since rvm and rbenv don't ever make their way
to a consumer there's no real reason to switch.

I suppose if you're someone who has to work with multiple Ruby versions, it
COULD save you time switching between them.

------
patrickslee
But there is <https://github.com/carsomyr/rbenv-bundler> already.

