How to read Gemfile
Tags: ruby
Published: 2021-06-12 13:41:11

## Motivation

When we join new projects, what we do first is to understand dependencies. Understanding dependencies helps us to grasp the scope of the project and to read source code smoothly.

For example, if it's a Rails project (and yes, we know it's a Rails project via `gem rails` line!), we can tell it treats parts of its data as trees with `acts_as_tree` gem installed. With `omniauth-github` the project should provide "login with GitHub" feature.

In Ruby, those dependencies are described in `Gemfile`, a file `Bundler` provides to define dependencies. Seasoned devs take a look at it and soon find some characteristics or problems.

On the other hand, novices in software development sometimes struggle to read Gemfile. Everything seems new and unfamiliar. There are too much information.

This article aims to help these people who find it difficult to understand dependencies when reading Gemfile.

## The basic of Gemfile

[The official man page](https://bundler.io/man/gemfile.5.html) describes the syntax of Gemfile, so I'd like to summarizes it here.

First of all, Gemfile is actually a Ruby file so you can do everything you can with Ruby. For example, you can define classes in Gemfile, though we usually don't have to do so. 

The most important part of Gemfile is `gem` declaration and version constraints. Others are less important.

### `gem`

`gem` declaration tells Bundler that we require that gem as a dependency. Typically it looks like:

```ruby
gem 'nokogiri'
```

In the example above, we tell Bundler that we need `nokogiri` gem as a dependency of the project.

You don't know what `nokogiri` does? No worry! We'll talk about how to look up each gem does later in this article.

### Version constraints

Each `gem` declaration may be followed by version constraints. It looks like this:

```ruby
gem 'nokogiri', '>= 1.0'
```

In this example, we tell Bundler we need `nokogiri` but it must be version `1.0` or newer. If there's no other dependencies that depend on older `nokogiri`, the latest one will be installed.

https://guides.rubygems.org/patterns/#pessimistic-version-constraint explains what we can do with version specifiers, so here we don't cover everything.

Version constraints are important because it indicates this dependency is treated somewhat different than others. We default to latest version so that we can benefit from new features and bugfixes. If we cannot use the latest version of that gem, there might be something we should take care of.

## How to know what the gem does

When we read `Gemfile`, we see a bunch of gem names. Some are famous, some are not. Each project has unique list of gems it depends. How should we look up their functionalities and why they're in the list?

There are two aspect in dependencies - what it does in general and why the project needs it. Let's talk one by one.

### What it does in general

Let's say we want to know what `nokogiri` does. The most reliable source is not something we find with google, but https://rubygems.org/, the official rubygems website.

The top page of the official rubygems site has a search box so just enter the name you want to know the feature of. That guides you to the search result page and you'll soon find a link to that gem. In this example you'll reach https://rubygems.org/gems/nokogiri.

On the right column, you'll see "homepage" link. Clicking that navigates us to the (yes) homepage of the gem. It might be a dedicated page of the project or a GitHub README, but it should explains what the gem is for. In this example the homepage of `nokogiri` is https://nokogiri.org/.

`nokogiri`'s homepage provides lots of information and you'll be probably satisfied. If there's no information you want, you should then search the web with the gem name ("nokogiri" in this example).

When you cannot find you're looking for with the homepage and web search, you might want to take a look at its source code. That's possible by clicking the "Source Code" link also on the right column of the gem page on https://rubygems.org

### Why the project needs it

Some gems are well known and every developer with some experience knows what they're for. Some gems are not that famous but provide good documentations. In these cases it's easy to understand what it provides to the project.

In some cases, however, you might want to know more about that gem. If the version constraint of the gem points to old version, you might want to know why you have to use that old version instead of newer or the latest one.

In those situations, bug trackers will help. You can go to bug tracker page by clicking "Bug Tracker" link on the right column. You can find some information about bugs the gem has in bug trackers and sometimes there's a bug that prevents you from using newer versions. For example, https://github.com/sparklemotion/nokogiri/issues is a issue tracker for `nokogiri` and we can find discussions around bugs.

Things get complicated when the gem is not well known or well documented. In this case, `grep` is your friend. Searching through the code using `grep` and other similar tools with the gem name will find the place where the gem is used. That also tells us why we need it.

## Conclusion

We illustrated how to read Gemfile and find the information we need on https://rubygems.org, issue trackers and the web.

Reading Gemfile enables us to know more about Ruby's ecosystem. It helps to reduce the possibility of reinventing the wheel and focus on more important things.