The idea of having multiple versions of ruby and multiple gemsets for each on your system at the same time, was confusing and abstract for me when I first started messing with ruby. So I dug in a bit to learn the landscape:
Why Gems in the first place?
Gems are just handy programs and libraries of code. Made a little X that helps you do something in all of your code? Wrap it up into a neat, self contained little package with RubyGems (upcoming post) and distribute it to the rest of the amazing ruby community to use! That package is called a gem.
Some gems prove incredibly useful and receive wide adoption, to the point where they are considered a standard part of using and building with ruby, such as rake, or a framework, such as Rails and Sinatra. Rails, Sinatra, rake, jQuery, etc. are all distributed as gems.
Programming languages are constantly evolving and being improved, as are the gems. It’s impossible for developers to improve and extend programming languages and programs while maintaining perfect compatibility with every gem or application built with it. If your whole application depends on the
mrhappytime gem and that gem works perfectly with ruby version 2.0.0, it’s possible that it won’t work at all with version 2.0.1. Gemsets and package managers like RVM and rbenv try to help solve this dependency trap by tying together versions of ruby and gems that already play well, and helping you organize and manage them.
A developer can have lots of rubies and gemsets on their system. First things first, everyone should know what version of ruby your currently running with ruby -v on my system:
ruby -v ruby 1.9.3p429 (2013-05-15 revision 40747) [x86_64-darwin12.3.0]
Again, ruby lets you keep various versions of ruby and various gemsets. A few basic exploratory commands (some using rvm, clearly):
rvm list known
* lists out all the versions and types of ruby ‘out there’
rvm list rubies
* lists just the different versions of ruby installed. ruby-#.#.# is the ruby version, and the -p### is the particular build. For me:
ruby-1.9.3-p429 [ x86_64 ] ruby-2.0.0-p195 [ x86_64 ] ruby-2.0.0-p247 [ x86_64 ]
* shows all gems installed locally, and the available versions of each
rvm list gemsets
* shows all rubies and gemsets installed locally. the part following the @ symbol is the name of the gemset. on my system:
1 2 3 4 5 6 7 8 9 10 11
Each gemset collection is independent of the others, so, for instance, if you have rails version 3.2.13 installed in one and switch to a new gemset you’ll have to reinstall it.
tying a directory to a version of ruby and a gemset- why? how different than using bundle? – bundle you’ll have to reinstall the gems each time you arrive at the project, if you’re not ‘in’/using the current gemset. – using the folder thing, you can make sure that whatever version of ruby and all of the billions of gems you might be using for a project, and their specific versions are all ‘there’ whenever you cd into that directory.
what’s the difference between so why do we need the gemfile and gemsets? can’t we fix all this with bundle?
to set a version of ruby for a given director: just need a .ruby file, with the ruby version in it
``` Show the present version of ruby $> ruby -v #=> ruby 1.9.3p429 (2013-05-15 revision 40747) [x86_64-darwin12.3.0] $> mkdir testtest $> cd testtest/ # Version still the same $> ruby -v #=> ruby 1.9.3p429 (2013-05-15 revision 40747) [x86_64-darwin12.3.0] # Writes the string "2.0.0" to the .ruby-version file, which is created at the time of writing. cat simply prints out the contents of the file. you can also open it with sublime etc and see what's there or edit it. $> echo 2.0.0 > .ruby-version $> cat .ruby-version #=> 2.0.0 # version? $> ruby -v #=> ruby 1.9.3p429 (2013-05-15 revision 40747) [x86_64-darwin12.3.0] # leave and return to the dir for the changes to take effect $> cd .. $> cd - $> ruby -v #=> ruby 2.0.0p195 (2013-05-14 revision 40734) [x86_64-darwin12.3.0] ``` alternative to echoing and piping is to: rvm --ruby-version use 1.9.3 --- which automatically creates the .ruby-verson file and adds the ruby v number to it
the slightly older way of doing this is by using the .rvmrc file, but if you use the .ruby-versions file your instructions are compatible with other ruby version managers like rbenv and chubby (link: ….) you can also specify the gemset in the same file by writing in the version number plus the gem, like: 2.0.0@gemname_to_use, but that might break this compatibility. rvm suggests using a separate .ruby-gemset file gemset basics resource at rvm: http://rvm.io/gemsets/basics“`
``` if you want to use an existing gemset called @mygemset rvm --ruby-version use 1.9.3@my_app ------- makes a .ruby-version file and the .ruby-gemset file if you just specify the gemset, it will just use the current gemset rvm --ruby-version use @global if you want to create a new gemset at the same time, simply append --create to the end $> rvm --ruby-version use @testtestgem --create $> rvm list gemsets … … #=> ruby-2.0.0-p195@testtestgem [ x86_64 ]
side note: you may have notice, that if you’ve already made one of these files, rvm will now time-stamp it and move it aside without deleting it
Again on the better late than never: gemsets are somewhat obsolete because of the awesomeness of bundle, but still “useful for binaries” – ie versions – so you can switch to a version and and start a new rails app etc.