module EventSourcery # This class provides a set of methods to help load and save aggregate instances. # # Refer to {https://github.com/envato/event_sourcery_todo_app/blob/31e200f4a2a65be5d847a66a20e23a334d43086b/app/commands/todo/amend.rb#L26 EventSourceryTodoApp} # for a more complete example. # @example # repository = EventSourcery::Repository.new( # event_source: EventSourceryTodoApp.event_source, # event_sink: EventSourceryTodoApp.event_sink, # ) # # aggregate = repository.load(Aggregates::Todo, command.aggregate_id) # aggregate.amend(command.payload) # repository.save(aggregate) class Repository # Create a new instance of the repository and load an aggregate instance # # @param aggregate_class Aggregate type # @param aggregate_id [Integer] ID of the aggregate instance to be loaded # @param event_source event source to be used for loading the events for the aggregate # @param event_sink event sink to be used for saving any new events for the aggregate def self.load(aggregate_class, aggregate_id, event_source:, event_sink:) new(event_source: event_source, event_sink: event_sink) .load(aggregate_class, aggregate_id) end # @param event_source event source to be used for loading the events for the aggregate # @param event_sink event sink to be used for saving any new events for the aggregate def initialize(event_source:, event_sink:) @event_source = event_source @event_sink = event_sink end # Load an aggregate instance # # @param aggregate_class Aggregate type # @param aggregate_id [Integer] ID of the aggregate instance to be loaded def load(aggregate_class, aggregate_id) events = event_source.get_events_for_aggregate_id(aggregate_id) aggregate_class.new(aggregate_id, events) end # Save any new events/changes in the provided aggregate to the event sink # # @param aggregate An aggregate instance to be saved def save(aggregate) new_events = aggregate.changes if new_events.any? event_sink.sink(new_events, expected_version: aggregate.version - new_events.count) end aggregate.clear_changes end private attr_reader :event_source, :event_sink end end