Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions lib/sequent/core/helpers/message_handler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,24 @@ module Helpers
#
module MessageHandler
module ClassMethods
def on(*args, **opts, &block)
def on(*args, **opts, &handler)
OnArgumentsValidator.validate_arguments!(*args)

message_matchers = args.map { |arg| MessageMatchers::ArgumentCoercer.coerce_argument(arg) }

unbound_method = begin
handler_method_name = :"__sequent_handler_#{handler.object_id}"
fail "duplicate method name #{handler_method_name}" if method_defined?(handler_method_name)

define_method(handler_method_name, &handler)
instance_method(handler_method_name)
ensure
undef_method(handler_method_name)
end

message_router.register_matchers(
*message_matchers,
block,
unbound_method,
)

opts.each do |name, value|
Expand Down Expand Up @@ -113,7 +123,9 @@ def dispatch_message(message, handlers)
if Sequent.logger.debug?
Sequent.logger.debug("[MessageHandler] Handler #{self.class} handling #{message.class}")
end
instance_exec(message, &handler)

args = handler.arity == 0 ? [] : [message]
handler.bind_call(self, *args)
end
end
end
Expand Down
44 changes: 40 additions & 4 deletions spec/lib/sequent/core/helpers/message_handler_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,15 @@ class UnrelatedHandlerWithOption
describe '.message_mapping' do
subject { MyHandler.message_mapping }

it 'returns a mapping of message classes to handlers' do
expect(subject).to eq(
MessageHandlerEvent => Set[MyHandler::FIRST_HANDLER, MyHandler::LAST_HANDLER],
MessageHandlerEventOtherEvent => Set[MyHandler::FIRST_HANDLER],
it 'returns a mapping of message classes to unbound methods' do
expect(subject.keys).to eq(
[
MessageHandlerEvent,
MessageHandlerEventOtherEvent,
],
)
expect(subject[MessageHandlerEvent].size).to eq(2)
expect(subject[MessageHandlerEventOtherEvent].size).to eq(1)
end

context 'given a non-class/module argument' do
Expand Down Expand Up @@ -211,4 +215,36 @@ class OtherHandler
end
end
end

describe 'handlers that use `return`' do
class HandlerWithReturn
include Sequent::Core::Helpers::MessageHandler

attr_reader :first_block_called, :second_block_called, :last_block_called

on MessageHandlerEvent do
@first_block_called = true
return
end

on MessageHandlerEvent do |_event|
@second_block_called = true
next
end

on MessageHandlerEvent do
@last_block_called = true
end
end

let(:handler) { HandlerWithReturn.new }

it 'should call subsequent handlers when a handler uses `return` or `next`' do
handler.handle_message(MessageHandlerEvent.new)

expect(handler.first_block_called).to be_truthy
expect(handler.second_block_called).to be_truthy
expect(handler.last_block_called).to be_truthy
end
end
end