I use RVM with gemsets and Bundler to manage my Ruby environment and dependencies. Some people question that. "Isn't RVM over-complicated?" they say. Or, "why are you using gemsets when you have bundler?" There are even some ethical objections: "I don't like how RVM overrides shell commands!"
Allow me to address these questions, starting with the easy one: RVM overrides shell commands, mainly the cd command so that it can detect environment files when we change directories. So what!? It just works and unless you're some kind of Shell Puritan that's all you should care about. Besides, many other apps and utilities use all kinds of shims and proxies and no-one bats an eyelid. Get over it! But what about complexity? Installing RVM involves a single command, two if you include downloading the gpg key. The vast majority of the RVM commands that I use daily are just a combination of the words use, gemset and create with a couple of list and install thrown in for good measure. Pretty simple really. Finally, why use gemsets? Surely, with Bundler there is no need to use gemsets any more, is there? Well, from a deployment point of view, this is correct. We can just deploy our Gemfile and Gemfile.lock and Bundler will ensure that the right versions of our gems are installed. Furthermore, Bundler can also tell us whether our gems are outdated or if we can upgrade the version of a specific gem without breaking others and other such wonderful stuff. However, from a development POV using gemsets is the cleanest and safest way to manage our environment. Consider a non-gemset set-up:
To make sure we use the correct version of our gems for our project we need to go through Bundler, which will look up the relevant Gemfile and use the appropriate gem. So Bundler knows ,for instance, that when we call rails we mean rails v5 within our current project and not v4. There are two problems with this approach:
By creating separate RVM gemsets for each of our projects, we get a physical separation of our dependencies. RVM stores ruby versions and gemsets in separate directories, so there are no potential conflicts. We still use Bundler to install our gems, but each bundle install now works within the context of the current gemset. This means that we don't have to call our rake or rails commands within the bundler context, as there is no need: we now know that the right dependencies will be in the right gemset. And when we finish with that protoype app we've been working on, we can just delete the app's gemset and get rid of these gems that we used as an experimental one-off.
RVM simply stores each permutation of <RubyVersion> and <Gemset> in separate directories. Whenever we decide to use a new Ruby Version or Gemset, RVM will just set our GEM_HOME and GEM_PATH environment variables to the appropriate directories. My Workflow I install commonly-used gems like bundler and nokogiri in the Global gemset. The Global gemset acts as a template from which all other gemsets are created. This means that whenever I create a new gemset, it will already include bundler and nokogiri.
rvm gemset use global
gem install bundler nokogiri When I start a new project, I create a new gemset for it
rvm gemset use myapp --create
////myapp gemset includes bundler and nokogiri In the case of Rails projects, I'll install the Rails version I want straight into my gemset. No, I don't put it in my Gemfile first and then call bundle; there's no need: the rails new generator will do that when I create my Rails project
gem install rails -v 5.0.0
rails new myapp Installing rails directly in my gemset also means that I know I'm using the right rails version, so i don't have to type bin/rails. I then create RVM config files .ruby-version and .ruby-gemset in my project directory. These files will be looked up by RVM whenever I cd into this directory so that RVM will load the right Ruby version and gemset for me.
cd myapp
rvm use --ruby-version 2.3.1@myapp ////creates .ruby-version .ruby-gemset And that's it. Simple and effective. Clean separation of dependencies, no faffing about with bundle exec and full control over my gems. Sweet! I'd love to hear how you manage your gems and dependencies. If you use other version managers, what makes them better / easier than RVM? Let me know.
6 Comments
Dmitry T.
10/14/2016 12:39:52 pm
If you store bundle setup in vendor folder of your project, for example, it's almost the same as gemset.
Reply
10/14/2016 07:37:56 pm
I use rbenv with Bundler and install dependencies with the --path option set to vendor/bundle. All the gem versions for my project are pulled down to this subdirectory of the project root, and Bundler and rbenv take care of the rest.
Reply
Fred Heath
10/14/2016 09:08:29 pm
Cool, thanks Chris! I think you can get RVM-equivalent functionality with rbenv, though last time I checked you had to install ruby-build and something else too IIRC. Don' know if that's still the case though.
Leo
10/17/2016 10:54:51 am
Could you please explain in detail how you configure the setup?. I really don't understand what you mean by saying that the gem versions are pulled down to the vendor/bundle subdirectory.
Fred Heath
10/14/2016 07:24:56 pm
Fair point Dmitry and thanks for bringing it up! Still, probably not quite as simple as $>rvm gemset delete myapp.
Reply
9/20/2017 12:02:55 pm
Any business owner will know that there is more to running a company than producing goods and services. It takes an immense amount of organization, and a photographic memory to keep on top of the demands on time and resources. The administration of the company alone can often be a full time job, let alone marketing, advertising, accounting, development and of course producing whatever it is they produce.
Reply
Leave a Reply. |
|