module Sequent
Constants
- AggregateRoot
Base class for all your domain classes.
load_from_history
functionality to be loaded_from_history, meaning a stream of events.- Command
Most commonly used
Command
Command
can be instantiated just by using:Command.new(aggregate_id: "1", user_id: "joe")
But the
Sequent::Core::Helpers::ParamSupport
also enables Commands to be created from a params hash (like the one from Sinatra) as follows:command = Command.from_params(params)
- CommandHandler
Base class for command handlers CommandHandlers are responsible for propagating a command to the correct
Sequent::Core::AggregateRoot
or creating a new one. For example:class InvoiceCommandHandler < Sequent::Core::BaseCommandHandler on CreateInvoiceCommand do |command| repository.add_aggregate Invoice.new(command.aggregate_id) end on PayInvoiceCommand do |command| do_with_aggregate(command, Invoice) {|invoice|invoice.pay(command.pay_date)} end end
- Event
Shortcut classes for easy usage
- Projector
Projectors listen to events and update the view state as they see fit.
Example of updating view state, in this case the InvoiceRecord table representing an Invoice
class InvoiceProjector < Sequent::Core::Projector manages_tables InvoiceRecord on InvoiceCreated do |event| create_record( InvoiceRecord, recipient: event.recipient, amount: event.amount ) end end
Please note that the actual storage is abstracted away in the
persistors
. Due to this abstraction you can not traverse persist or traverse child objects like you are used to do with ActiveRecord. The following example will not work:invoice_record.line_item_records << create_record(LineItemRecord, ...)
In this case you should simply do:
create_record(LineItemRecord, invoice_id: invoice_record.aggregate_id)
- Secret
Shortcut
- VERSION
- ValueObject
ValueObject
is a container for data that belongs together but requires no identityIf something requires identity is up to you to decide. An example in for instance the invoicing domain could be a person’s Address.
class Address < Sequent::Core::ValueObject attrs street: String, city: String, country: Country end
A
ValueObject
is equal to anotherValueObject
if and only if allattrs
are equal.You can copy a valueobject as follows:
new_address = address.copy(street: "New Street")
This a deep clone of the address with the street attribute containing “New Street”
- Workflow
Public Class Methods
Short hand for Sequent.configuration
.aggregate_repository
# File lib/sequent/sequent.rb, line 58 def self.aggregate_repository configuration.aggregate_repository end
Short hand for Sequent.configuration
.command_service
# File lib/sequent/sequent.rb, line 40 def self.command_service configuration.command_service end
# File lib/sequent/sequent.rb, line 35 def self.configuration Configuration.instance end
Setup Sequent
.
Setup is typically called in an initializer
or setup phase of your application. A minimal setup could look like this:
Sequent.configure do |config| config.enable_autoregistration = true end
Calling configure a second time will create a new configuration
# File lib/sequent/sequent.rb, line 29 def self.configure Configuration.reset yield Configuration.instance Configuration.instance.autoregister! end
# File lib/sequent/sequent.rb, line 62 def self.dry_run(*commands) Sequent::Util::DryRun.these_commands(commands) end
Short hand for Sequent.configuration
.logger
# File lib/sequent/sequent.rb, line 53 def self.logger configuration.logger end
# File lib/sequent/sequent.rb, line 48 def self.migration_class Class.const_get(configuration.migrations_class_name) end
# File lib/sequent/sequent.rb, line 14 def self.new_uuid Sequent.configuration.uuid_generator.uuid end
# File lib/sequent/sequent.rb, line 44 def self.new_version migration_class.version end