module RailsEventSourcing::Command
The Base command mixin that commands include.
A Command
has the following public api.
“‘
MyCommand.call(user: ..., post: ...) # shorthand to initialize, validate and execute the command command = MyCommand.new(user: ..., post: ...) command.valid? # true or false command.errors # +> <ActiveModel::Errors ... > command.call # validate and execute the command
“‘
‘call` will raise an `ActiveRecord::RecordInvalid` error if it fails validations.
Commands including the ‘RailsEventSourcing::Command` mixin must:
-
list the attributes the command takes
-
implement ‘build_event` which returns a non-persisted event or nil for noop.
Ex:
“‘
class MyCommand include RailsEventSourcing::Command attributes :user, :post def build_event Event.new(...) end end
“‘
Public Instance Methods
Define the attributes. They are set when initializing the command as keyword arguments and are all accessible as getter methods.
ex: ‘attributes :post, :user, :ability`
# File lib/rails-event-sourcing/command.rb, line 57 def attributes(*args) attr_reader(*args) initialize_method_arguments = args.map { |arg| "#{arg}:" }.join(', ') initialize_method_body = args.map { |arg| "@#{arg} = #{arg}" }.join(";") initialize_definition = <<~CODE def initialize(#{initialize_method_arguments}) #{initialize_method_body} after_initialize end CODE class_eval(initialize_definition) end
Run validations and persist the event.
On success: returns the event On noop: returns nil On failure: raise an ActiveRecord::RecordInvalid error
# File lib/rails-event-sourcing/command.rb, line 48 def call(*args) new(*args).call end
A new record or nil if noop
# File lib/rails-event-sourcing/command.rb, line 84 def event @event ||= (noop? ? nil : build_event) end
# File lib/rails-event-sourcing/command.rb, line 88 def noop? false end
Private Instance Methods
Hook to set default values
# File lib/rails-event-sourcing/command.rb, line 106 def after_initialize # noop end
Returns a new event record or nil if noop
# File lib/rails-event-sourcing/command.rb, line 101 def build_event raise NotImplementedError end
Save the event. Should not be overwritten by the command as side effects should be implemented via Reactors triggering other Events.
# File lib/rails-event-sourcing/command.rb, line 96 def execute! event.save! end