Skip to content

Instantly share code, notes, and snippets.

@jgarth
Last active August 25, 2016 17:15
Show Gist options
  • Save jgarth/cc687ee77236bcfd2227023ad7b02c76 to your computer and use it in GitHub Desktop.
Save jgarth/cc687ee77236bcfd2227023ad7b02c76 to your computer and use it in GitHub Desktop.
AASM Transitional Hooks DSL / Spec / Implementation / Playground
require 'rails_helper'
describe 'AASM hooks' do
class Foo
include AASM
include Concerns::TriggersHooksAfterAASMStateChanges
aasm do
state :pending, initial: true # waiting for manual review
state :reviewed # either manual or auto; waiting for arrive, could be in transit
event :review do
transitions from: :pending, to: :reviewed
end
end
def vendors
return [FooVendor]
end
end
class FooVendor
include Concerns::DefinesHooksForAASMStateChanges
register_transition_hook klass: Foo, from_state: :pending, to_state: :reviewed do
raise 'FooTransitionHookCalled'
end
end
describe 'Vendor objects' do
it 'can register hooks' do
expect(FooVendor.aasm_state_change_hooks).to_not be_blank
end
end
describe 'Hook-calling objects' do
it 'asks all vendors for hooks' do
allow(FooVendor).to receive(:aasm_state_change_hooks).and_call_original
foo = Foo.new()
expect do
foo.review!
end.to raise_error('FooTransitionHookCalled')
expect(FooVendor).to have_received(:aasm_state_change_hooks)
end
end
end
module Concerns::DefinesHooksForAASMStateChanges
extend ActiveSupport::Concern
included do
class << self
attr_reader :aasm_state_change_hooks
def register_transition_hook(klass:, from_state:, to_state:, &block)
@aasm_state_change_hooks ||= []
@aasm_state_change_hooks << { klass: klass, from_state: from_state,
to_state: to_state, block: block }
end
end
end
end
module Concerns::TriggersHooksAfterAASMStateChanges
extend ActiveSupport::Concern
included do
aasm do
after_all_transitions :trigger_hooks
end
def vendors
[]
end
end
private
def trigger_hooks
hooks = vendors.flat_map { |v| v.aasm_state_change_hooks }.compact.uniq
hooks.select do |hook|
hook[:klass] === self &&
(hook[:from_state] == aasm.from_state || hook[:from_state].blank?) &&
hook[:to_state] == aasm.to_state
end.each do |hook|
hook[:block].call(self)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment