No commit activity in last 3 years
No release in over 3 years
Sequel extension that allows savepoints to force running after_commit and after_rollback hooks
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

>= 0
>= 0

Runtime

~> 5.28
 Project Readme

Sequel::ForceHooks

Sequel extension that allows to trigger after_commit and after_rollback hooks on savepoints.

This is particularly useful for testing callbacks side-effects on transaction tests (and probably in no other circumstances).

Installation

Add this line to your application's Gemfile:

gem 'sequel-force-hooks'

And then execute:

$ bundle install

Or install it yourself as:

$ gem install sequel-force-hooks

Requirements

sequel-force-hooks requires sequel 5.28.0 or newer, if you need to use an older version try this gem instead: sequel-savepoint-hooks.

Usage

Let's say you have transactional tests setup and want to make sure you callbacks' side-effects callbacks run properly. This could force you to treat it as a special case, moving all the transactional logic inside the test, with this gem you can forget about all the extra complications and simply write your test like any other, focusing on what you actually care.

In order to benefit from this gem you need to setup you test suite for transactional testing as usual and tell the sequel DB to run all the registered callbacks on the savepoint you want instead of the outermost one. Let's see an example using RSpec.

Say we have a FooService class that puts a job for background execution.

# lib/foo_service.rb

class FooService
  def call
    DB.transaction do
      # Do some work here...

      # Only run if commit was successful
      after_commit do
        FooWorker.perform_async
      end
    end
  end
end

We want to test that the FooWorker was enqueued only if the commit was successful.

We need to setup our transactional test suite to run the callbacks after the outermost transaction call at FooService, like it would happen in production. To that end, we need to setup a transaction around our test examples to discard any DB changes (using rollback: :always), set auto_savepoint: true (to create a savepoint inside the first transaction inside our code) and pass the force_hooks: :nested option, this will force the callbacks to run at the savepoint level.

# spec/spec_helper.rb

# Setup your DB connection as usual
DB = Sequel.connect('mysql2://user:@localhost:3306/my_test_db')

# Load the :force_hooks extension only for the test suite
DB.extension(:force_hooks)

RSpec.configure do |config|
  # Config RSpec as usual...

  # Setup an around hook for every test
  config.around(:each) do |example|
    # Tell sequel to rollback your tests after every example has run, setup a savepoint on the first
    # innermost transaction and ran all the callbacks there by passing 'force_hooks: :nested'
    DB.transaction(rollback: :always, auto_savepoint: true, force_hooks: :nested) do
      example.run
    end
  end
end

And finally we test that a FooWorker job was enqueued properly:

# spec/foo_spec.rb

require 'spec/spec_helper'

RSpec.describe FooService do
  context 'when is successful' do
    subject(:foo_service) { FooService.new }

    before do
      foo_service.call
    end

    it 'must enqueue a job' do
      expect(FooWroker.jobs).to eq(1)
    end
  end
end

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/pabloh/sequel-force-hooks.

License

The gem is available as open source under the terms of the MIT License.

Thanks

  • Jeremy Evans (@jeremyevans), for creating the awesome sequel gem
  • Chris Hanks (@chanks), for creating the sequel-savepoint-hooks extension, that originally inspired this gem