Gems and Bundler

Ruby · Practical · 12 min

Every real Ruby project, Rails included, manages its dependencies with Bundler.

A gem is a packaged Ruby library, published on rubygems.org. gem install rubocop installs one globally, and require "json" loads a library into your program. The standard library ships many default and bundled gems (json, csv, set, net-http, minitest).

For projects, use Bundler. A Gemfile declares what the project needs:

source "https://rubygems.org"
gem "faraday", "~> 2.12"
group :development, :test do
  gem "rspec", "~> 3.13"
end

bundle install resolves compatible versions and writes Gemfile.lock with the exact version of every gem, including transitive ones. Commit the lock file for applications so every machine and server runs identical code. bundle add faraday edits the Gemfile and installs in one step; bundle update faraday deliberately upgrades one gem; bundle outdated lists available upgrades.

The pessimistic operator ~> 2.12 means >= 2.12 and < 3.0; ~> 2.12.1 means < 2.13.

Run commands with `bundle exec` (bundle exec rspec) so they use the locked versions, not whatever is installed globally. In code, require "bundler/setup" does the same. Rails apps include binstubs like bin/rails that do it for you.

A library you publish is described by a .gemspec; bundle gem name scaffolds one. Version managers such as rbenv, chruby, asdf or mise switch Ruby versions per project via .ruby-version.

Example

# Shell session
bundle init                       # creates a Gemfile
bundle add faraday --version "~> 2.12"
bundle add rspec --group "development,test"
bundle install                    # writes Gemfile.lock

cat Gemfile.lock | grep -A1 "faraday ("   # exact resolved version

bundle exec ruby -e 'require "faraday"; puts Faraday::VERSION'
bundle outdated                   # what could be upgraded
bundle update faraday             # upgrade just this gem (within ~>)

echo "3.4.7" > .ruby-version      # picked up by rbenv / chruby / mise
bundle gem my_tool                # scaffold a publishable gem

Remember

  • Gemfile declares dependencies; Gemfile.lock pins exact versions
  • Commit Gemfile.lock for applications
  • Use bundle exec (or binstubs) to run with the locked versions

Watch out for

  • Running a tool without bundle exec and getting a different global version than the project expects.

Check yourself

  1. What range does gem "rack", "~> 3.1" allow?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: bundler.io/guides/getting_started.html

Gems and Bundler · Ruby · Topolearn