What is a Ruby gem?
A gem is a package that you can download & install. When you require an installed gem you’re adding extra functionality to your Ruby program.
Gems allow you to:
That’s just some examples. Every gem has it’s own goal.
Why do we use gems?
Thanks to RubyGems, we have a rich ecosystem of helpful libraries just one
gem install away!
A list of gems required for a given (non-gem) project can be listed on a special file called “Gemfile” so they can be automatically installed by Bundler. Both covered later in this guide.
What are some examples of gems?
Most gems are pure Ruby code.
A few gems include a Ruby C extension for improved performance.
This extension is built automatically for you when you install the gem. In some cases, you may need to manually install additional software that is not managed by RubyGems.
Let’s learn more about gems by building your own & looking at the files that make a gem.
You can prepare the files for a new gem by running
bundle gem <name>.
bundle gem awesome_gem
A Gem is composed of the following structure:
├── awesome_gem.gemspec ├── bin │ ├── console │ └── setup ├── Gemfile ├── lib │ ├── awesome_gem │ │ └── version.rb │ └── awesome_gem.rb ├── Rakefile ├── README.md └── test ├── awesome_gem_test.rb └── test_helper.rb
.gemspec file is where you’ll find all the information about the gem.
The gem version itself is defined as a constant in
Here’s an example gemspec:
Gem::Specification.new do |spec| spec.name = "awesome_gem" spec.version = AwesomeGem::VERSION spec.authors = ["Jesus Castello"] spec.summary = "Example gem for article about Ruby gems" spec.files = Dir['**/**'].grep_v(/.gem$/) spec.require_paths = ["lib"] spec.add_development_dependency "bundler", "~> 1.16" spec.add_development_dependency "rake", "~> 10.0" spec.add_development_dependency "minitest", "~> 5.0" end
require_paths array is where Ruby will look for your gem files when you require them. This allows you to put your code under
lib/<gem_name>/ & then require it with
A file named
lib/awesome_gem/parser.rb would be required as
require "awesome_gem/parser" from anywhere inside the gem.
You will have most of your requires in
lib/<gem_name>.rb (the only file at the root of
That’s the file that gets loaded when you
require the gem!
add_development_dependency lines define gems that you’re going to use during development.
These are gems like minitest, RSpec, or pry.
add_dependency defines gems that you use as part of your code.
Once you’ve changed the summary & description from the default values… you’ll able to load an irb session with your gem using the
bin/console program that
bundle gem creates for you.
$ bin/console irb(main):001:0> irb(main):002:0> irb(main):003:0> AwesomeGem => AwesomeGem irb(main):004:0> irb(main):005:0> AwesomeGem::VERSION => "0.1.0"
Then you can package the gem using
gem build <name>.gemspec & publish it to rubygems.org using
While learning about Ruby gems you may also read about Bundler.
But what is Bundler exactly?
Bundler is a tool for dependency management.
Didn’t RubyGems already handle this?
Well, it does… but only for the gems themselves.
Your regular Ruby application isn’t built as a gem, so it doesn’t get this feature.
That’s why Bundler exists!
Have you seen those
That’s where you write what gems you want to use for your Ruby application.
These gems will be loaded for you without having to
A Gemfile looks like this:
ruby '2.5.0' gem 'rails', '~> 5.2.1' gem 'sqlite3' gem 'puma', '~> 3.11' gem 'bootsnap', '>= 1.1.0', require: false
Bundler (and RubyGems since version 2.0) can read this file & install the requested versions of these gems.
This is what you should see when running the
bundle install command:
Using turbolinks-source 5.1.0 Using turbolinks 5.1.1 Using uglifier 4.1.18 Using web-console 3.6.2 Bundle complete! 18 Gemfile dependencies, 78 gems now installed. Use `bundle info [gemname]` to see where a bundled gem is installed.
What are these symbols (like
~>) used when declaring the versions for every gem in your Gemfile?
These allow you to request a range of versions.
You can say things like, “I want the version to be equal or greater than 1.2, but less than 2.0”.
Which would look like this:
gem 'puma', '~> 1.2'
~> is a shortcut for this range:
gem 'puma', '>= 1.2', '< 2.0'
In the case of
~> 5.2.1, it means exactly this:
'>= 5.2.1', '< 5.3'
The more specific the version number is the more restricted the version range will be.
You have a few options when requiring a gem inside a Gemfile.
You may want to pull a gem from a different source, like GitHub.
This is helpful when you need to use the latest version of the project, even if it hasn't been released on rubygems.org yet.
Here's an example:
gem "rails", git: "email@example.com:rails/rails.git"
You can pass a
branch option to use the code from a branch that isn't master.
gem "awesome_print", git: "firstname.lastname@example.org:awesome-print/awesome_print.git", branch: "v2"
Another option you may find is
What does that do?
It tells Bundler to not auto-require the gem for you. This means that you'll have to
require it in your code when you need it.
This is used for gems that are limited in scope.
Gems that you use in a specific rake task, but you don't use in your Rails controllers & models. The benefit is that you save memory in your app code because you only load that gem when you need it.
You can also group gems by environment.
That means you can have gems that are only installed & loaded in development (like
Finally, bundler creates a
What's the difference?
Gemfile.lock is auto-generated & it says exactly what versions of every gem were installed.
Bundler will install these versions so when you deploy this application to production, or share your project with other developers, everyone will be working with an identical set of gems.
|gem list||List all your installed gems. Accepts an argument for filtering gems by name (example:
|gem which <name>||Gives you the path where a gem is installed.|
|gem search <name>||Search gems from configured sources (default: rubygems.org). Takes a regular expression (example:
|gem env||Displays information about your gem environment (version, paths, configuration).|
|gem install <name> -v <version>||Allows you to install a specific gem version (example:
|bundle viz||Generates a visualization of the dependency graph for your current project.|
|bundle show||Shows info about a particular gem installed via bundler. Must be inside a folder with a Gemfile.|
|bundle outdated||Displays a list of outdated gems in the current project. Can use the
|bundle console||Runs an irb session with the gems from the current project's Gemfile.|
You've learned about RubyGems, the package system for Ruby. You've also learned how a gem is structured, what is a Gemfile, Bundler & the difference between the
Gemfile & the
I hope you found this useful!
Please share this article, subscribe to the newsletter if you haven't yet (9000+ Ruby developers!) & check out my Ruby book.
Thanks for reading & have a great day 🙂