Ruby Gems and Bundler
Master Ruby's package management system with gems and Bundler. Learn to manage dependencies, create gems, and publish to RubyGems.
Bundler Basics
Gemfile
source 'https://rubygems.org'
Ruby version
ruby '3.3.0'
Production gems
gem 'rails', '> 7.1'
gem 'pg', '>= 1.1'
gem 'puma', '> 6.0'
Development and test gems
group :development, :test do gem 'rspec-rails' gem 'factory_bot_rails' gem 'faker' end
Development only
group :development do gem 'rubocop' gem 'rubocop-rails' end
Test only
group :test do gem 'capybara' gem 'selenium-webdriver' end
Git source
gem 'my_gem', git: 'https://github.com/user/my_gem.git'
Local path (for development)
gem 'local_gem', path: '../local_gem'
Specific branch
gem 'experimental_gem', git: 'https://github.com/user/repo.git', branch: 'develop'
Require specific file or false to not auto-require
gem 'sidekiq', require: 'sidekiq/web' gem 'bootsnap', require: false
Version Constraints
Exact version
gem 'rails', '7.1.0'
Pessimistic operator (allows patch updates)
gem 'rails', '> 7.1.0' # >= 7.1.0 and < 7.2.0
gem 'rails', '> 7.1' # >= 7.1.0 and < 8.0.0
Greater than or equal
gem 'pg', '>= 1.1'
Range
gem 'ruby-version', '>= 1.0', '< 2.0'
Multiple constraints
gem 'nokogiri', '>= 1.10', '< 2.0'
Bundler Commands
Install all gems from Gemfile
bundle install
Install to specific path
bundle install --path vendor/bundle
Update all gems
bundle update
Update specific gem
bundle update rails
Check for outdated gems
bundle outdated
Show gem location
bundle show rails
Execute command with bundled gems
bundle exec rspec
Open gem in editor
bundle open rails
Check Gemfile syntax
bundle check
Remove unused gems
bundle clean
List all installed gems
bundle list
Show dependency tree
bundle viz
Gemfile.lock
The Gemfile.lock file locks gem versions for consistent installations:
Always commit Gemfile.lock to version control
This ensures all developers use same gem versions
Regenerate Gemfile.lock
rm Gemfile.lock bundle install
Creating Gems
Gem Structure
Create new gem
bundle gem my_gem
Structure:
my_gem/ ├── lib/ │ ├── my_gem/ │ │ └── version.rb │ └── my_gem.rb ├── spec/ │ ├── my_gem_spec.rb │ └── spec_helper.rb ├── bin/ │ ├── console │ └── setup ├── .gitignore ├── Gemfile ├── LICENSE.txt ├── my_gem.gemspec ├── Rakefile └── README.md
Gemspec
my_gem.gemspec
require_relative 'lib/my_gem/version'
Gem::Specification.new do |spec| spec.name = "my_gem" spec.version = MyGem::VERSION spec.authors = ["Your Name"] spec.email = ["your.email@example.com"]
spec.summary = "Short summary of gem" spec.description = "Longer description of what gem does" spec.homepage = "https://github.com/username/my_gem" spec.license = "MIT"
spec.required_ruby_version = ">= 3.0.0"
spec.metadata["homepage_uri"] = spec.homepage spec.metadata["source_code_uri"] = "https://github.com/username/my_gem" spec.metadata["changelog_uri"] = "https://github.com/username/my_gem/CHANGELOG.md"
Specify which files should be added to the gem
spec.files = Dir.chdir(File.expand_path(dir)) do
git ls-files -z.split("\x0").reject do |f|
f.match(%r{\A(?:test|spec|features)/})
end
end
spec.bindir = "exe" spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) } spec.require_paths = ["lib"]
Runtime dependencies
spec.add_dependency "activesupport", "~> 7.0" spec.add_dependency "nokogiri", ">= 1.10"
Development dependencies
spec.add_development_dependency "rspec", "> 3.12"
spec.add_development_dependency "rubocop", "> 1.50"
end
Version File
lib/my_gem/version.rb
module MyGem VERSION = "0.1.0" end
Main Library File
lib/my_gem.rb
require_relative "my_gem/version" require_relative "my_gem/core" require_relative "my_gem/helpers"
module MyGem class Error < StandardError; end
def self.configure yield configuration end
def self.configuration @configuration ||= Configuration.new end
class Configuration attr_accessor :api_key, :timeout
def initialize
@api_key = nil
@timeout = 30
end
end end
Building and Publishing
Build Gem
Build gem locally
gem build my_gem.gemspec
This creates my_gem-0.1.0.gem
Install locally for testing
gem install ./my_gem-0.1.0.gem
Uninstall
gem uninstall my_gem
Publish to RubyGems
First time setup (one-time)
gem push my_gem-0.1.0.gem
You'll be prompted to log in
For subsequent pushes
gem push my_gem-0.2.0.gem
Yank a version (removes from RubyGems)
gem yank my_gem -v 0.1.0
Unyank a version
gem unyank my_gem -v 0.1.0
Versioning
Semantic Versioning: MAJOR.MINOR.PATCH
1.0.0 -> 1.0.1 (patch)
1.0.1 -> 1.1.0 (minor)
1.1.0 -> 2.0.0 (major)
lib/my_gem/version.rb
module MyGem VERSION = "1.0.0" end
Update version, then build and push:
1. Edit version.rb
2. gem build my_gem.gemspec
3. gem push my_gem-1.0.0.gem
RubyGems Commands
List installed gems
gem list
Search for gems
gem search rails
Show gem info
gem info rails
List gem dependencies
gem dependency rails
Update all gems
gem update
Update specific gem
gem update rails
Cleanup old versions
gem cleanup
Show gem environment
gem env
Install specific version
gem install rails -v 7.1.0
Install without documentation (faster)
gem install rails --no-document
Uninstall gem
gem uninstall rails
Fetch gem but don't install
gem fetch rails
Gem Groups
Define groups
group :development do gem 'pry' end
group :test do gem 'rspec' end
group :development, :test do gem 'factory_bot' end
Install without specific groups
bundle install --without production
Require specific groups
Bundler.require(:default, :development)
Gem Sources
Primary source
source 'https://rubygems.org'
Additional sources
source 'https://gems.example.com' do gem 'private_gem' end
Git sources
gem 'my_gem', git: 'https://github.com/user/my_gem.git' gem 'my_gem', git: 'https://github.com/user/my_gem.git', tag: 'v1.0' gem 'my_gem', git: 'https://github.com/user/my_gem.git', branch: 'main' gem 'my_gem', git: 'https://github.com/user/my_gem.git', ref: 'abc123'
GitHub shorthand
gem 'my_gem', github: 'user/my_gem'
Local path
gem 'my_gem', path: '../my_gem'
Requiring Gems
In code
require 'my_gem'
Bundler auto-requires gems based on Gemfile
To disable auto-require:
gem 'my_gem', require: false
Then manually require where needed:
require 'my_gem'
Require specific file
gem 'sidekiq', require: 'sidekiq/web'
Platform-Specific Gems
Only install on specific platforms
gem 'pg', platforms: :ruby gem 'sqlite3', platforms: [:mingw, :mswin, :x64_mingw]
Multiple platforms
platforms :ruby do gem 'pg' gem 'nokogiri' end
platforms :jruby do gem 'activerecord-jdbc-adapter' end
Private Gems
Using Private Gem Server
Gemfile
source 'https://rubygems.org'
source 'https://gems.mycompany.com' do gem 'private_gem' end
Using Git Credentials
.netrc file for private repos
machine github.com login your-username password your-token
Gem Development
Using bundle console
Open IRB with gem loaded
bin/console
Or
bundle console
Running Tests
Using Rake
rake spec
Or directly
bundle exec rspec
Local Development
In your app's Gemfile, point to local gem
gem 'my_gem', path: '../my_gem'
Or use bundle config
bundle config local.my_gem ../my_gem
Best Practices
-
Always commit Gemfile.lock to version control
-
Use pessimistic versioning (~>) for stability
-
Keep gems updated but test thoroughly
-
Use groups to separate dev/test/production gems
-
Specify Ruby version in Gemfile for consistency
-
Use bundle exec to ensure correct gem versions
-
Document gem dependencies and why they're needed
-
Test gems locally before publishing
-
Follow semantic versioning for your gems
-
Keep gemspecs clean and well-documented
Anti-Patterns
❌ Don't commit vendor/bundle to git (use .gitignore) ❌ Don't use require: false unnecessarily - adds manual work ❌ Don't specify exact versions unless absolutely necessary ❌ Don't push untested gem versions to RubyGems ❌ Don't include unnecessary files in gem packages ❌ Don't hardcode credentials in gemspec or Gemfile
Troubleshooting
Clear bundler cache
bundle clean --force
Regenerate Gemfile.lock
rm Gemfile.lock && bundle install
Check for gem conflicts
bundle exec gem dependency
Verbose output
bundle install --verbose
Show why a gem is needed
bundle show rails
List all gem versions
bundle list
Related Skills
-
ruby-oop - For structuring gem code
-
ruby-metaprogramming - Used in many gems
-
ruby-standard-library - Core Ruby functionality