Command Bus

Command Pattern - decoupling what is done from who does it.


Registering commands and their handlers

require "arkency/command_bus"

command_bus =
register = command_bus.method(:register)

{ FooCommand => event_store).method(:foo), BarCommand => }.map(&register)

Invoking command bus with a command


Will call FooService#foo method with the command you just passed.

New instance of a service for every invoked command

If you need a new instance of a service, every time it is called with a command, or you want to lazily load the responsible services, use Proc when registering commands.

command_bus =
command_bus.register(FooCommand, ->(foo_cmd) { dep).foo(foo_cmd) })
command_bus.register(BarCommand, ->(bar_cmd) { })

Working with Rails development mode

In Rails development mode when you change a registered class, it is reloaded, and a new class with same name is constructed.

a = User
# => 40737760

# Reloading...

b = User
# => 48425300

h = { a => 1, b => 2 }
# => 2

a == b
# => false

so your Hash with mapping from command class to service may not find the new version of reloaded class.

To workaround this problem you can use to_prepare callback which is executed before every code reload in development, and once in production.

config.to_prepare do
  config.command_bus =
  register = command_bus.method(:register)

  { FooCommand => event_store).method(:foo), BarCommand => }.map(&register)

and call it with

Convenience alias

require "arkency/command_bus/alias"

From now on you can use top-level CommandBus instead of Arkency::CommandBus.