# Gems

# What is a gem?

A gem is the equivalent to a plugin or an extension for the programming language ruby.

To be exact even rails is nothing more than a gem. A lot of gems are built on rails or other gems (they are dependent of said gem) or are standalone.

# In your Rails project

# Gemfile

For your Rails project you have a file called Gemfile. In here you can add gems you want to include and use in your project. Once added you need to install the gem by using bundler (See Bundler section).

# Gemfile.lock

Once you have done this, your Gemfile.lock will be updated with your newly added gems and their dependencies. This file locks your used gems so they use that specific version declared in that file.

GEM
remote: https://rubygems.org/
specs:
devise (4.0.3)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 4.1.0, < 5.1)
responders
warden (~> 1.2.3)

This example is for the gem devise. In the Gemfile.lock the version 4.0.3 is declared, to tell when installing your project on an other machine or on your production server which specified version to use.

# Development

Either a single person, a group or a whole community works on and maintains a gem. Work done is usually released after certain issues have been fixed or features have been added.

Usually the releases follow the Semantic Versioning 2.0.0 (opens new window) principle.

# Bundler

The easiest way to handle and manage gems is by using bundler. Bundler (opens new window) is a package manager comparable to bower.

To use bundler you first need to install it.

gem install bundler

After you have bundler up and running all you need to do is add gems to your Gemfile and run

bundle

in your terminal. This installs your newly added gems to your project. Should an issue arise, you would get a prompt in your terminal.

If you are interested in more details, I suggest you have a look at the docs (opens new window).

# Gemfiles

To start, gemfiles require at least one source, in the form of the URL for a RubyGems server.

Generate a Gemfile with the default rubygems.org source by running bundle init. Use https so your connection to the server will be verified with SSL.

source 'https://rubygems.org'

Next, declare the gems that you need, including version numbers.

gem 'rails', '4.2.6'
gem 'rack',  '>=1.1'
gem 'puma',  '~>3.0'

Most of the version specifiers, like >= 1.0, are self-explanatory. The specifier ~> has a special meaning. ~> 2.0.3 is identical to >= 2.0.3 and < 2.1. ~> 2.1 is identical to >= 2.1 and < 3.0. ~> 2.2.beta will match prerelease versions like 2.2.beta.12.

Git repositories are also valid gem sources, as long as the repo contains one or more valid gems. Specify what to check out with :tag, :branch, or :ref. The default is the master branch.

gem 'nokogiri', :git => 'https://github.com/sparklemotion/nokogiri', :branch => 'master'

If you would like to use an unpacked gem directly from the filesystem, simply set the :path option to the path containing the gem's files.

gem 'extracted_library', :path => './vendor/extracted_library'

Dependencies can be placed into groups. Groups can be ignored at install-time (using --without) or required all at once (using Bundler.require).

gem 'rails_12factor', group: :production

group :development, :test do
  gem 'byebug'
  gem 'web-console', '~> 2.0'
  gem 'spring'
  gem 'dotenv-rails'
end

You can specify the required version of Ruby in the Gemfile with ruby. If the Gemfile is loaded on a different Ruby version, Bundler will raise an exception with an explanation.

ruby '2.3.1'

# Gemsets

If you are using RVM(Ruby Version Manager) then using a gemset for each project is a good idea. A gemset is just a container you can use to keep gems separate from each other. Creating a gemset per project allows you to change gems (and gem versions) for one project without breaking all your other projects. Each project need only worry about its own gems.

RVM provides (>= 0.1.8) a @global gemset per ruby interpreter. Gems you install to the @global gemset for a given ruby are available to all other gemsets you create in association with that ruby. This is a good way to allow all of your projects to share the same installed gem for a specific ruby interpreter installation.

Creating gemsets

Suppose you already have ruby-2.3.1 installed and you have selected it using this command:

rvm use ruby-2.3.1

Now to create gemset for this ruby version:

rvm gemset create new_gemset

where the new_gemset is the name of gemset. To see the list of available gemsets for a ruby version:

rvm gemset list

to list the gems of all ruby versions:

rvm gemset list_all

to use a gemset from the list (suppose new_gemset is the gemset I want to use):

rvm gemset use new_gemset

you can also specify the ruby version with the gemset if you want to shift to some other ruby version:

rvm use ruby-2.1.1@new_gemset

to specify a default gemset for a particular ruby version:

rvm use 2.1.1@new_gemset --default

to remove all the installed gems from a gemset you can empty it by:

rvm gemset empty new_gemset

to copy a gemset from one ruby to another you can do it by:

rvm gemset copy 2.1.1@rails4 2.1.2@rails4

to delete a gemset:

rvm gemset delete new_gemset

to see the current gemset name:

rvm gemset name

to install a gem in the global gemset:

rvm @global do gem install ...

Initializing Gemsets during Ruby Installs

When you install a new ruby, RVM not only creates two gemsets (the default, empty gemset and the global gemset), it also uses a set of user-editable files to determine which gems to install.

Working in ~/.rvm/gemsets, rvm searchs for global.gems and default.gems using a tree-hierachy based on the ruby string being installed. Using the example of ree-1.8.7-p2010.02, rvm will check (and import from) the following files:

~/.rvm/gemsets/ree/1.8.7/p2010.02/global.gems
~/.rvm/gemsets/ree/1.8.7/p2010.02/default.gems
~/.rvm/gemsets/ree/1.8.7/global.gems
~/.rvm/gemsets/ree/1.8.7/default.gems
~/.rvm/gemsets/ree/global.gems
~/.rvm/gemsets/ree/default.gems
~/.rvm/gemsets/global.gems
~/.rvm/gemsets/default.gems

For example, if you edited ~/.rvm/gemsets/global.gems by adding these two lines:

bundler
awesome_print

every time you install a new ruby, these two gems are installed into your global gemset. default.gems and global.gems files are usually overwritten during update of rvm.

# Remarks

# Gemfile documentation

For projects that are expected to grow, it is a good idea add comments your Gemfile. That way, even in large setups you will still know what each gem does even if the name is not self-explanatory and you added it 2 years ago.

This can also help you to remember why you chose a certain version and consequently re-evaluate the version requirement later on.

Examples:

# temporary downgrade for TeamCity
gem 'rake', '~> 10.5.0'
# To upload invoicing information to payment provider
gem 'net-sftp'