The hoptoad_notifier library has traditionally been a Rails-only plugin. Although the majority of the code was not Rails-specific, the internals of the notifier were not decoupled such that the notifier parts could be loaded without also using the Rails-specific catcher parts.
However, at the end of last year, we released a newly refactored hoptoadnotifier plugin that targetted our brand new v2 server API, as well as sporting improved separation of concerns. Starting with version 2.0 of hoptoadnotifier, the notifier code was usable outside of Rails applications.
The quest for a reusable notifier
Unfortunately, it was still packaged as a Rails plugin, which made it difficult to build libraries based on it or use it in non-Rails applications. A number of people have requested a gem version of the library, and we’re happy to provide one. However, we thought it would be a good idea to explain some of the reasons that we were unable to provide a gem sooner.
The folly of two distribution methods
For a while, we tried packaging the notifier as both a plugin as a gem. Although using the gem version had some advantages, it made it much more difficult for us to identify problems that our users were experiencing. There was a different set of common problems for plugin users and gem users, and without access to our users' codebases or servers, it was often impossible to debug anything without a game of 20 questions that was frustrating to our users.
In the end, we decided that our users would be happier with fewer possibilities to debug. When we released version 2 of the notifier, we decided to wait until the gem was fully supported, and then switch to that entirely. However, before restricting our users to the gem, we wanted to make sure that the installation and configuration process remained seamless, and there were a few issues with Rails and gems that stood in our way.
The pitfalls of Rails and gems
There are a few things that “just work” in plugins that Rails treats very differently in gems. Rails does not automatically load rake tasks from gems, and Capistrano only looks for recipes in plugins. Additionally, gems could potentially be installed on the system, vendored in the vendor/gems directory, or both. To make matters worse, handling of gems has changed substantially through the history of Rails, and we don’t want to abandon our users that aren’t on the latest and greatest Rails.
Generators (sort of) to the rescue
We decided to add one more step to the install process: running the “hoptoad” generator. This has the added benefit of generating an appropriate configuration file and automatically running the integration test for new users. However, generators in gems suffer from similar problems to rake tasks: old versions of Rails only look for generators in gems ending in “_generator,” and some newer versions won’t load generators from vendored gems.
What’s a toad to do?
In the end, we decided to add an automated test to make sure that the catcher, notifier, and installer continue to work on various versions of Rails. We wrote up some Cucumber features that go through the whole process, starting from a freshly built hoptoad_notifier gem, continuing with installing and configuring the notifier in a freshly generated Rails application, and ending with receiving a test notification. The test runs several different scenarios (vendored gems, installed gems, and so on) and runs for every supported version of Rails. If you’d like to see this in action, check it out on Github.
What’s in it for me?
As a user of Hoptoad, this means two things:
If you’re using a Rails application, the installation and upgrade process has changed slightly:
# in config/environment.rb config.gem 'hoptoad_notifier' # from your Rails root: $ rake gems:install $ rake gems:unpack GEM=hoptoad_notifier $ script/generate hoptoad --api-key your_key_here
If you’re writing a library or non-Rails application, using hoptoad_notifier is now much easier:
require 'rubygems' require 'hoptoad_notifier' HoptoadNotifier.configure do |config| config.api_key 'your_key_here' end HoptoadNotifier.notify(:error_message => 'Krakow')
So go ahead and “gem install hoptoad_notifier,” and send all your Rails (or not) errors to the toad!