Why does RVM install duplicate gems for different gemsets? - ruby

So, I've created a separate rvm gemset for each of my rails projects. They both use the same version of ruby 1.9.3.
This causes bundle install to completely install a fresh set of gems for both projects. It doesn't matter if the other project has the exact same version of the gem installed in the other gemset. I'm guessing this is the expected behavior to me but it seems like an inefficient use of hard drive space and bandwidth.
I know that I could manually move some of those gems to a global gemset, but that seems tedious to me and also prone to breaking if my dependencies change for a particular project.
Is there a better way to organize things, or have rvm auto detect when a gem version is already installed and just use that copy?
Or is there a better alternative to RVM that I should be using.

This is by design. Gemsets allow you to completely isolate the libraries used so you don't have any accidental interaction between projects. If you don't need the isolate you can just use an interpreter without a gemset:
rvm use 1.9.3
If there are a few gems you use across all projects, just switch to the global gemset for the interpreter:
rvm use 1.9.3#global
gem install the common gems and then they won't be re-installed per-project anymore when you are in a gemset.
While gemsets definitely aren't efficient in terms of bandwidth or HD space, they are extremely handy because you can easily blow away all dependencies for a project and re-bundle from scratch any time you want to. They also completely eliminate accidentally changing versions of your dependencies. If you don't like gemsets, correctly specifying versions in your Gemfile can get you pretty far on this without them.
As far as alternatives, rbenv is the main one I'd check out.

Related

bundler vs RVM vs gems vs RubyGems vs gemsets vs system ruby [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 9 years ago.
Improve this question
I am new to Ruby and trying to wrap my head around following concepts: bundler vs RVM vs gems vs RubyGems vs gemsets vs system rub and I'm confused.
Can someone please describe a 'best practice' of how I should manage all this on a fresh install of the latest version of Ubuntu? What should I install, and how should I use it all?
I'm guessing that doing a sudo apt-get install ruby is not be recommended, but I am not sure. I tried it on my system in addition to 'all the other Ruby stuff'. It's just adding to my confusion. I am not talking about Rails but just regular Ruby gems (e.g. Vagrant, Chef, scripts).
As per the previous answer, this is quite a lot to cover, so consider this a short introduction.
gems are the way Ruby libraries are packaged. They are to Ruby what jars are to Java. Inside a gem file, you find Ruby code (.rb files), but also tests, and a special file giving information on the gem itself, such as its name, dependencies and version (gemspec). Any Ruby project can define the gems it needs via a Gemfile that just need to declare dependencies. Rubygems is the name of the package manager - the tool used to install the packages (while the gems are the packages themselves). Rubygems is now part of Ruby.
Bundler is what makes managing gems bearable. Based on your Gemfile, a simple call to bundler using bundle install will download and install all the required gems. Using standard gem command, you would have to install each of them manually, using gem install <gem_name>. Bundler is not part of Ruby (it is itself packaged as a gem), but it a "de facto standard" for most applications (you will not find many people not using it, and no good reasons not to use it, actually).
RVM is a tool allowing you to install multiple versions of Ruby on a machine, switching between them when needed. This can be used to install both a Ruby 1.8 and 1.9, or even a "MRI" (Matz's Ruby, the default implementation) and alternatives (such as JRuby or Rubinius). Note that RVM is not alone in this field, see for instance rbenv.
A gemset in RVM is a set of gems specific to a given context, typically a project. This is useful if you are for example developing different applications, each with its own sets of gems, and want to keep them separate.
system Ruby is, when using RVM, the Ruby version installed on the machine (ie, not via RVM).
If you are just starting, gems and bundler are of interest to you. You can let RVM and gemsets aside for now.
You're asking for more information in one question than is in-scope for Stack Overflow. To cover it all would take a book.
On Ubuntu it's easy to install and remove gems to the "system" version of Ruby, so get used to installing and removing regular gems via sudo. (On Mac OS I'd give different advice because Apple bundles Ruby for their own use and it's not a great idea to mess with it.) Then, when you have an idea how the whole gem idea works, and you know you want multiple Ruby versions on your system, try "rbenv" or "RVM" and install a version or two in your sandbox.
Linux makes it easy to add/remove Ruby via a distribution, but we're limited to the versions the distro maintainers have packaged, so I usually install from source. But, that's a pain when managing several versions of Ruby for development, test and production systems, which is why rbenv and RVM were invented -- they handle the dirty detail allowing us to concentrate on programming.
I've used both rbenv and RVM, and have been using rbenv for the last six months or so, with good results. It's less complicated than RVM which I like. In either case they make it easy to have different versions installed, with separate sets of Gems. You can have different Ruby versions open in different terminal windows if you want, making it easy to test for compatibility.
Rule one when debugging is to make changes one at a time, which is true for learning to program or learning a new language. Don't be distracted, just keep it simple.

Updated ruby, then gemsets via rvm upgrade, but .rvmrc files?

I'm not sure if my workflow is off, or if I'm using rvm gemsets entirely wrong, but here's how I upgraded to the latest patch level in Ruby today [327].
Updated ruby via rvm install.
Ran rvm upgrade and upgraded everything
Selected yes, when asked during rvm upgrade to delete old ruby.
So, then I noticed that my .rvmrc files in my apps were trying to load the old gemset that now doesn't exist. I manually updated each .rvmrc file with the new gemset from the rvm upgrade.
All is well, but my questions:
Should I have kept my prior version of ruby installed just in case?
Is manually updating each .rvmrc the right thing to do?
Should I be creating gemsets for each app, or should I really just use gemsets to manage ruby versions for different required environments?
1- Patches don't really change much thing that can accidentally break your code. Keep just major versions. (1.8.7, 1.9.2, 1.9.3, etc)
2- This way is the fastest and simplest way. It works flawless and really don't have any problem.
3- Gemsets are good for organization purposes. I really like to have on for each project, but i guess i and kind of a control freak, so i believe it is personal taste.

Why should I use application-specific RVM gemsets in addition to Bundler?

I'm using RVM to manage my local Ruby installations, and Bundler for application dependency management.
Some people recommend using a separate RVM gemset for each application, while some seem to think that's not necessary.
So what are the advantages of using a separate RVM gemset for each application, when I'm using Bundler anyway? What are the risks of not doing so?
i use gemsets in addition to bundler because of the following:
easy to just drop everything once a while (i like messing around with my installed gems)
no need to call bundle exec (this is obsolete with binstubs)
faster loading, because less gem-specs need to be parsed
easy to distribute (copy it to your mates)
there are probably more reasons to use them, but i generally like the idea of sandboxes!
I've found that it's useful to have rvm if you're using rails 2. RVM is great if you need to work on an app that has old code. Rails 2 doesn't use a Gemfile, so bundle exec doesn't work. RVM makes it easy to keep the gem versions correct for that project, and they you can switch back to newer versions of rails and use the Gemfile to specify versions. If you have multiple apps that use different gem versions, but the same version of ruby, it's convenient to share most of the gems, and specify them in the Gemfile where they differ.
I think it's kind of case dependent. If you find that there are tons of version issues between two apps, and constantly modifying Gemfiles to keep them straight is annoying, then use separate gemsets. If there is enough in common, it might make sense to just use the same gemset
RVM gemsets allow you to separate gems without loading bundler - which is faster, it will be simpler to load the gems.
You should be using gemsets to just separate projects from your helper gems (like gist).
But if you decide that gemsets are of no help for you you can tell RVM to ignore gemsets totally:
echo "export rvm_ignore_gemsets_flag=1" >> ~/.rvmrc
Might I also refer you to the 'globalcache' documentation in the form of an rvm-test located at fast/globalcache_comment_test.sh in conjunction with your projects' Gemfile.
This will also cut down on the network traffic to rubygems.org. Initial loadout of global, not withstanding.

How can I install a gem as if it was specified in a Gemfile?

I want to install a gem via gem install, but I need it to resolve with dependencies of the current project.
Basically I want the functionality that bundler gives me when I specify gem 'xyz' in a Gemfile, but I don't want to add that specific gem into the Gemfile.
I tried doing bundle exec gem install ... but it doesn't seem to work.
edit: The reason why I don't want to add it to the Gemfile is that it might be something like metric_fu, metrical, saikuro, rails_best_practices, etc. Simply gems that are kind of utility use and might only cluttler the project.
I might only want to use them temporarily, or install them, try out, if it doesn't work out the way I want do rvm gemset empty and bundle install again to clean up.
The point of Bundler is, in part, to prevent you from doing things like that (to prevent you from injecting gems from outside when your project doesn't declare them).
Looking for a way of doing that is looking for a bug in Bundler. If you did manage to find some way of skirting Bundler's enforcement mechanisms, you should probably not use it; instead, you may consider filing it as a bug with Bundler's issue tracker.
Now we come to the real questions: what can you do? and what should you do?
You should use either RVM gemsets or Bundler to isolate your application and its gem dependencies. You don't need both. I would recommend Bundler for this purpose over RVM gemsets.
You should add to your Gemfile any gems that you want to use and that integrate with your application (i.e., that either load your application or that are loaded as part of your application). This is not a requirement for any gems that refrain from integrating with your application.
You should refrain from committing a changed Gemfile or Gemfile.lock to version control until you are satisfied that your application continues to operate acceptably (tests pass, new gem does something useful, etc.).
Or you should stop using Bundler, because you want to do things it is explicitly designed to prevent you from doing (not recommended).
At the risk of sounding dumb, why not add it to the gemfile? You can always add it to its own group if you don't want to have to install it everywhere.
A slightly different approach is, if you're using version control, such as Git, to create a new branch and install the gems. If it doesn't work out, uninstall the gem (I'm not sure this will be done by bundle update on the old branch) and trash the branch. If it does, work, merge your stuff into the old the branch.
Though I do believe the other answers and comments have some very good points.

Benefits of RVM

Why should I/should I not use RVM?
I'm new to the ruby language and servers as a whole. I've had some trouble installing using RVM...so I'm inclined to not use it right now, but it seems like it may make installations down the road easier?
I'm interested to hear about your experience with RVM and your thoughts as it pertains to maintaining a server.
RVM is useful even if you don't want to install multiple versions at the same time. I'm a ruby hobbyist (PHP during the day :(), and I have no reason to want to use old versions, but I still use RVM.
Installing ruby is a pain. Getting it from the package manager (at least in ubuntu) gives you an outdated version that changes installation directories from the defaults. I've had nothing but problems with it.
So you think, "I'll just build it from source". Building from source requires getting a load of dependencies and configuring options. Often times I've built ruby only to find out I forgot to enable SSL support or readline support.
RVM takes care of all of this. In 3 or so commands, you have a perfectly built version of ruby.
And I didn't even cover how RVM manages multiple ruby installations for you, which is its killer feature. If you have that need, there is really no other sane solution.
RVM is great as this allows your to install different versions without touching your system's default Ruby install. It is rather similar to virtualenv's in Python.
Another great advantage to having RVM are the gemsets - you can create as many gemsets that are unique to the version, and patch level, of ruby.
I've extolled some of its virtues here and you should also see this blog post.
In terms of maintaining a server - let's take a Passenger install for example; do remember that Passenger is installed as a gem, so with rvm the benefit here is that you can have multiple installs of passenger, tied to a different version of ruby. Of course, typically, you'll have Passenger running on one version at a time, although there are ways to have Passenger, in particular, running on different ruby versions.
I use different Ruby versions for different projects (that's where .rvmrc is really handy). Some deployment environments are happy with 1.9, while there are a couple of legacy servers using 1.8 for some reasons. Also, occasionally I want to launch a specific version of ruby to compare how they work. RVM does all that for me.
When you are first getting used to Ruby, it may not entirely be necessary. That said, what it does is set you up for success in the future. Because once you get hooked, you may end up playing with projects that need to move from, say, MRI 1.8.x to 1.9.x. Or from 1.9.x, to JRuby 1.6.x. My experience is that this happens irregularly, but when it does, there's no substitute for RVM.
Outside of that, the other biggest feature that I use regularly, is the ability to segment one particular release. So I can have an environment for 'stable' gems, and an environment for 'unstable' gems. For instance, while Rails 3.1 has been in release candidate mode, I've had one main workspace for 1.9.2 and a separate space for Rails 3.1.rc? gems on 1.9.2. That makes it possible for me to keep developing my main Rails 3.0 stuff (with one command at the CLI), without having to specify full file paths to the appropriate rails bin files in order to use the older files.
If you're using a Debian based platform where the packagers/policy leads to a really bad default installation you'll have a way better experience using rvm.

Resources