Hacking Your Gems for Debugging

In an excellent post on Codenoble, Adam Crownoble explains [What To Do When You’re Stuck In Ruby][codenoble]. It was validating to read about someone else using a lot of the same tricks for digging in to software libraries. It also inspired me to share some tricks that I use frequently.

In one portion of the article, Adam mentions that you may encounter the need to hack up one of your local gems in order to gain a better understanding of what’s going on. The method prescribed is to clone the gem, make your alterations, then install from a git path using Bundler. This is a great method if you need to share your hacked up version of the gem with other developers, but it’s a bit heavy for quick & dirty debugging. I use the following technique to make direct edits to my gems, then revert back to a pristine install.

The workflow I use looks something like this:

1. Encounter a confusing outcome related to a gem.
1. Open the gem for editing and dig around to get oriented: `bundle open [GEM]`
1. Make alterations, run my application, iterate, resolve.
1. Run `bundle exec gem pristine [GEM]` to revert the gem back to its unaltered state.

Occassionally I’ll use the following at a shell prompt to probe around the gem files without opening the entire directory in my editor.

$ open $(bundle show rails)

This opens the gem directory in Finder under OS X.

Below is an overview of the available commands that support this workflow. Using these commands, you can use this workflow regardless of whether you’re using Bundler or bare Rubygems.

If you’re using bundler:

`bundle open [GEM]` – Opens the Gem’s base install dir in your editor.
`bundle show [GEM]` – Outputs the Gem’s base install dir.
`bundle exec gem pristine [GEM]` – Reinstalls the Gem to its unaltered state.

Interestingly, there is a [long-open Bundler feature request][bundlepristinefeature] for a `bundle pristine [GEM]` command that would eliminate the `bundle exec` call required to revert the gem while using Bundler.

If you’re using bare Rubygems:

`gem open [GEM]` – Opens the gem’s base install dir in your editor.
`gem which [GEM]` – Outputs the location of a gem’s primary library file.
`gem pristine [GEM]` – Reinstalls the gem to its unaltered state.

When using the `open` variant of these commands, Rubygems/Bundler will use the editor configured in your environment.

[Rubygems][rubygemsopen] looks at: `GEM_EDITOR`, `VISUAL`, `EDITOR`, and finally reverts to `vi` if none of these are configured.

[Bundler][bundleropen] looks here: `BUNDLER_EDITOR`, `VISUAL`, `EDITOR`, and will complain if none are set.

I only set `VISUAL` and `EDITOR` because most software packages respect these two. Only use the RubyGems and Bundler specific environment variables if you want to use an editor that isn’t consistent with your normal preferences.

If you’re a polyglot, and you’re looking for something that helps you achieve similar goals with a variety of languages, have a look at the [Qwandry gem][qwandry], which allows you to open Python, Perl, Node, and Rubygems (maybe more) libraries in similar fashion to Rubygems and Bundler. You’re on your own for reverting edits though.

[codenoble]: http://codenoble.com/blog/what-to-do-when-youre-stuck-in-ruby/

[rubygemsopen]: https://github.com/rubygems/rubygems/blob/c6b4946f84a1a291a9c6f072bcc2832617f33888/lib/rubygems/commands/open_command.rb

[bundleropen]:https://github.com/bundler/bundler/blob/7be4f29c7caaccead7a6d9014839a8b3a63da315/lib/bundler/cli/open.rb

[bundlepristinefeature]:https://github.com/bundler/bundler-features/issues/5

[qwandry]: https://github.com/adamsanderson/qwandry