Kieran Klaassen

I'm Kieran, a creator and engineer, composer and baker. I craft with love, creating code to croissants. Curiosity and discovery shape my life. I try to inspire others and stay true to myself.

← All thoughts

I wrote a Gem! It runs instance_methods in a job

I've been writing Ruby for 12 years, but I'd never written a Ruby gem 💎! I wanted to build one I'd use myself. The point was to learn how gem internals and testing work; the functionality came second.

Introducing the Laters Gem

🔥 You can check it out on GitHub.

It runs any instance method on an Active Record model in a job: add _later to the method name. The idea came from Action Mailer's deliver_later, which schedules a job instead of delivering immediately.

Here's an example of using it in a project:

class User < ApplicationRecord
  include Laters::Concern

  after_create_commit :notify_user_later
  after_commit :refresh_cache_later

  private

  def notify_user
    # External services
    Sms.send(to: user.phone, message: 'Hey!')
  end

  def refresh_cache!
    # Expensive calculation
  end
end

How to write a Gem

Here's how I wrote the gem. I started with Bundler's gem command:

$ bundle gem laters
$ cd laters

You get a whole lot for free. I love this generator!

The lib

The gem's entry point is lib/laters.rb.

Since my gem was going to run in a Rails environment, I added Rails as a dependency.

laters.gemspec

  spec.add_dependency 'rails', '>= 4.2'

I ended up requiring the dependencies and library files like this:

lib/laters.rb

require 'active_model'
require 'active_job'
require 'laters/version'
require 'laters/concern'
require 'laters/instance_method_job'

module Laters
  class Error < StandardError; end
end

You can see the concern and job implementations on GitHub. They aren't important to the gem-creation process, so I won't cover them here.

Test it!

Next I needed to test the functionality, so I looked at how other gem authors did it. In Andrew Kane's Ahoy gem, I found this test helper.

So what's Combustion?

Simple, elegant testing for Rails Engines

That sounded like what I wanted. It gives you a really nice Rails-like app inside your test suite. You can create models, a database, a controller, and jobs—whatever you need to test your gem against. It feels like adding your gem to an app's Gemfile.

With RSpec, it's super easy to set up. Run this to generate a skeleton Rails app in spec/internal:

$ bundle exec combust

Then enable it in your specs by adding the parts of Rails you need to the spec helper:

Combustion.initialize! :active_record, :action_controller

Then write your specs as if you were in a normal Rails app. This is great! 🔥🚀

Run the tests with:

$ rake test

Release it

When everything is tested and working, you can release it. Check the version number, add a changelog if you like that sort of thing, and run:

$ rake release

And now it's live on RubyGems.org/gems/laters.

This is a high-level overview, and it assumes you already have a good understanding of Ruby. But these were the missing pieces I had no idea how to do before I wrote this gem. There are probably better ways to handle some of them; I got here by reading a lot of source code from gems I really like.