Last week in a dev team meeting, we got a very raw question from a new hire,

"What's with all these gems? They seem like black magic to me!"

My response at the time was, "You will become familiar with all these gems through experience." But that was a very unhelpful response on my part. The truth is, through experience I discovered specific techniques for learning about ruby gems. This blog post is an attempt to catalog those techniques for the new rubyist.

Where to start

The first place to look for rubygems is your project's Gemfile. This is a file placed in the root directory of your project that lists all gems on which your application depends. The bundler tool, which is itself a gem, reads the Gemfile and installs the correct versions of all the gems and their dependencies when you run the bundle install command.

# sample Gemfile for a rails app
source 'https://rubygems.org'

gem 'rails', '4.2.4'
gem 'pg'
gem 'jbuilder', '~> 2.0'
gem 'unicorn'
# etc...

However, if your project is not an application, but instead a ruby gem, you will not find the gems listed in the Gemfile.

source 'https://rubygems.org'

# Specify your gem's dependencies in GEM_NAME.gemspec
gemspec

Instead, you will find the gem dependencies listed in GEM_NAME.gemspec, where GEM_NAME is the actual name of the gem for which you are viewing the source. Look for the spec.add_dependency and spec.add_development_dependency lines to discover the gem names.

Gem::Specification.new do |spec|
  spec.name          = "GEM_NAME"
  # ...more gem metadata

  spec.add_dependency "redis"
  spec.add_dependency "redis-namespace"

  spec.add_development_dependency "rake", "~> 10.0"
  spec.add_development_dependency "rspec"

Searching for gems

Once you find a gem you want to learn about, the next step is to read the documentation for that gem. Fortunately, almost all open source gems are hosted on RubyGems.org, the ruby community's gem hosting service. When you go to the RubyGems.org homepage and search for the gem by name, it will show an informative page with the gem's name, description, version history, dependencies, author, and more.

chasqui on rubygems

In the bottom right-hand corner of the page, you will also find links to the gem's home page, source code, documentation, and more. For must rubygems, exploring these links are sufficient for learning what a gem does and how to use it. The links RubyGems shows are specified in GEM_NAME.gemspec, so if you are already viewing the gem's source code (see below), you can find these links in the gemspec, too.

Viewing the source

Eventually you will encounter incomplete documentation, find a bug in a gem, or become curious about how a gem works. In these cases, the documentation is not sufficient and you need to view the gem's source code.

To view the source code for the latest version of an installed gem, you can use the gem open command. The gem open command will open the gem's source code in your EDITOR of choice. See also gem help open for more options.

gem open jbuilder

But what if you have multiple versions of a gem installed and need to view the source for an older version? This is often the case when you are on a team that maintains multiple rails apps and you have not yet upgraded all of them to the latest version. Fortunately, bundler has an equivalent command for such a purpose.

bundle open activerecord

Finally, if you do plan on contributing to a project, you will actually want to fork and clone the gem's repository so you can contribute your changes upstream. In that case, use the links on RubyGems.org or in the gemspec to find where the gem's source code is hosted.

Advanced techniques

Sometimes you will not know the name of the gem you are searching for. This most often is the case when you encouter a mysterious method that is not working as expected and you have no idea which gem it is from (assuming it's not a method defined in your project). For this situation we can use ruby's #source_location method to tell us not only which gem defines the method, but also the exact file name and line number on which the method is defined.

irb(main)> User.method(:belongs_to).source_location
=> ["/Users/jordan/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.4/lib/active_record/associations.rb, 1514]

Recap

Here is what we learned in this post:

  • How to find gems in your Gemfile or gemspec
  • How to search for gems on RubyGems.org to find their source code and documentation
  • How to view the source for installed gems with gem open and bundle open
  • How to find which gem defines a method with ruby's #source_location method

Hopefully, ruby gems seem a little less like black magic to you now. Happy coding!