Bundler and Gems
A gem is a packaged Ruby library — code, metadata, and a version number bundled into a distributable .gem file, typically published to the public registry at rubygems.org. Gems are how the Ruby community shares everything from tiny utility libraries to entire frameworks like Rails. Bundler is the tool that manages which gems (and which exact versions) a given project depends on, resolving a consistent set of compatible versions across every gem's own dependencies and recording that resolution in a lockfile so every machine that installs the project gets byte-for-byte identical dependency versions.
Cricket analogy: A gem is like a certified bat model sold by a manufacturer, ready to use out of the box; Bundler is like the equipment manager who ensures every player on the squad uses the exact same approved bat model and grip tape, recorded on an equipment sheet everyone follows.
Installing and requiring gems directly
At the lowest level, gem install <name> downloads and installs a gem, and require "gem_name" loads it into a running Ruby program. This works fine for quick scripts and experimentation, but it doesn't record which version was used, doesn't handle a project with dozens of interdependent gems, and can silently break if a gem's dependency updates in an incompatible way — exactly the problems Bundler exists to solve.
Cricket analogy: gem install is like a club buying one bat on the spot without recording the model, which works for a friendly match but breaks down once you have a whole squad needing consistent gear across seasons -- exactly the problem an equipment manager (Bundler) solves.
# quick_script.rb — fine for a one-off script, not for a real project
require "json"
require "httparty" # gem install httparty first
response = HTTParty.get("https://api.example.com/status")
puts JSON.pretty_generate(response.parsed_response)The Gemfile and bundle install
A Gemfile declares every gem a project depends on, optionally pinned to a version constraint, and grouped by environment (development, test, production). Running bundle install resolves a version of every gem (and every gem's own dependencies) that satisfies all the constraints simultaneously, installs them, and writes the exact resolved versions to Gemfile.lock. From then on, bundle install on any other machine reads Gemfile.lock first and installs those exact versions — this is what makes builds reproducible across developers, CI, and production.
Cricket analogy: A Gemfile is like a squad selection sheet listing every player and their required role, grouped by format (Test, ODI, T20); running bundle install is like the selection committee finalizing the exact eleven that satisfies every constraint and recording it on the official team sheet (Gemfile.lock) for the whole tour.
# Gemfile
source "https://rubygems.org"
ruby "3.3.0"
gem "rails", "~> 7.1"
gem "pg", "~> 1.5"
group :development, :test do
gem "rspec-rails"
gem "pry"
end
group :test do
gem "factory_bot_rails"
endThe ~> operator is called the "twiddle-wave" or pessimistic version constraint. gem "pg", "~> 1.5" means "any version from 1.5 up to, but not including, 2.0" — it allows patch and minor updates but blocks major-version changes that might break compatibility.
Gemfile.lock and bundle exec
Gemfile.lock records the exact resolved version of every gem in the dependency tree, not just the top-level ones you listed — this file should always be committed to version control for applications (though typically not for libraries/gems themselves). Running a script with bundle exec ruby script.rb (or bundle exec rspec, bundle exec rails server) ensures the exact gem versions from the lockfile are loaded, rather than whatever versions happen to be installed globally on the machine, which is what prevents "works on my machine" dependency mismatches.
Cricket analogy: Gemfile.lock is like the final confirmed team sheet listing every player, including reserves, that should be filed with the match officials; running bundle exec is like the umpires checking that exact sheet before play starts, rather than trusting whoever happens to be standing at the boundary that day.
Manually editing Gemfile.lock, or committing a Gemfile change without re-running bundle install, is a common source of confusing errors — always let Bundler regenerate the lockfile via bundle install (or bundle update for intentional upgrades) rather than hand-editing it.
- A gem is a packaged, versioned Ruby library distributed via RubyGems (typically rubygems.org).
- The Gemfile declares a project's dependencies and version constraints, optionally grouped by environment.
- bundle install resolves compatible versions across the whole dependency tree and writes them to Gemfile.lock.
- Gemfile.lock should be committed for applications so every environment installs identical gem versions.
- The
~>pessimistic operator constrains upgrades to compatible minor/patch versions while blocking breaking major-version bumps. - bundle exec runs a command using the exact gem versions from Gemfile.lock, avoiding version mismatches with globally installed gems.
Practice what you learned
1. What is the primary purpose of Gemfile.lock?
2. What does the version constraint `gem "pg", "~> 1.5"` allow?
3. Why should application projects (as opposed to gem/library projects) commit Gemfile.lock to version control?
4. What does `bundle exec rspec` accomplish that running `rspec` directly might not?
5. What is the recommended way to update Gemfile.lock after changing a version constraint in the Gemfile?
Was this page helpful?
You May Also Like
RSpec Testing Basics
Get started with RSpec, Ruby's most popular behavior-driven testing framework, covering describe/it blocks, expectations, matchers, and test organization with let and before hooks.
Intro to Ruby on Rails
An overview of the Rails web framework, its MVC architecture, and the convention-over-configuration philosophy that lets developers build database-backed apps quickly.
Installing Ruby and Using IRB
How to install Ruby with a version manager, verify your setup, and use IRB (Interactive Ruby) to experiment with code in real time.
Ruby Quick Reference
A condensed cheat sheet of core Ruby syntax, common Enumerable methods, and idioms for fast lookup while coding.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics