Skip to content
AgileLogics
6 min read

Gems and Bundler

Prerequisites: Requiring files and libraries

A gem is a packaged Ruby library. The public registry, rubygems.org, hosts over 180,000 of them — for web frameworks, testing, HTTP clients, database drivers, and much more.

Installing a gem directly

gem install colorize

That's fine for trying something out, but real projects use Bundler so every developer and every server gets exactly the same gem versions.

Bundler: Gemfile and Gemfile.lock

In a new project folder:

bundle init
bundle add colorize

bundle init creates a Gemfile listing the project's dependencies. bundle add adds a gem to it and installs it:

# Gemfile
source "https://rubygems.org"

gem "colorize", "~> 1.1"

Bundler also writes Gemfile.lock, which records the exact version of every gem (including the gems your gems depend on). Commit both files to version control. Anyone else runs bundle install to get identical versions.

Version constraints

Constraint Means
"1.1.0" exactly 1.1.0
">= 1.1" 1.1 or newer — including future majors
"~> 1.1" at least 1.1, but below 2.0
"~> 1.1.2" at least 1.1.2, but below 1.2

~> (the "pessimistic" or "twiddle-wakka" operator) is the usual choice: it accepts bug fixes and new features but not a new major version that might break your code.

Using the gem

require "bundler/setup"   # use exactly the versions in Gemfile.lock
require "colorize"

puts "Success!".green

Run commands with bundle exec to make sure the locked versions are used: bundle exec ruby app.rb, bundle exec rspec.

Groups

Gems only needed for development or testing go in a group, so they're not installed on production servers:

group :development, :test do
  gem "rspec", "~> 3.13"
  gem "rubocop", require: false
end

Common mistakes

  • Not committing Gemfile.lock for an application, so production gets different gem versions than development. (Libraries — gems you publish — follow a different convention; that's covered in Level 3.)
  • Running rspec instead of bundle exec rspec and picking up a different globally-installed version.
  • Adding gems for trivial tasks. Every dependency is code you trust and must keep updated — check the standard library first.