Class: Aggregates::AggregateRoot

Inherits:
EventProcessor show all
Defined in:
lib/aggregates/aggregate_root.rb

Overview

An AggregateRoot is a central grouping of domain object(s) that work to encapsulate parts of our Domain or Business Logic.

The general design of aggregate roots should be as follows:

- Create functions that encapsulate different changes in your Aggregate Roots. These functions should enforce
constraints on the application. Then capture state changes by creating events.

- Create event handlers that actually performed the state changes captured by the events
  made by processing commands using the above functions.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from MessageProcessor

#find_message_handlers, #handle_message, included

Constructor Details

#initialize(id, mutable: true) ⇒ AggregateRoot

Creates a new instance of an aggregate root. This should not be called directly. Instead, it should be called by calling AggregateRoot.get_by_id. :reek:BooleanParameter



26
27
28
29
30
31
32
33
# File 'lib/aggregates/aggregate_root.rb', line 26

def initialize(id, mutable: true)
  super()

  @id = id
  @mutable = mutable
  @sequence_number = 1
  @event_stream = EventStream.new id
end

Instance Attribute Details

#idObject (readonly)

Returns the value of attribute id.



14
15
16
# File 'lib/aggregates/aggregate_root.rb', line 14

def id
  @id
end

Class Method Details

.get_by_id(id) ⇒ Object

Returns a new instance of an aggregate by loading and reprocessing all events for that aggregate.



17
18
19
20
21
# File 'lib/aggregates/aggregate_root.rb', line 17

def self.get_by_id(id)
  instance = new id
  instance.replay_history
  instance
end

Instance Method Details

#apply(event, params = {}) ⇒ Object

Takes an event type and some parameters with which to create it. Then performs the following actions

1.) Builds the final event object.
2.) Processes the event locally on the aggregate.
3.) Produces the event on the event stream so that is saved by the storage backend and processed
    by the configured processors of the given type.

Raises:

  • (FrozenError)


45
46
47
48
49
50
51
# File 'lib/aggregates/aggregate_root.rb', line 45

def apply(event, params = {})
  raise FrozenError unless @mutable

  event = build_event(event, params)
  process_event event
  @event_stream.publish event
end

#process_event(event) ⇒ Object



35
36
37
38
# File 'lib/aggregates/aggregate_root.rb', line 35

def process_event(event)
  super
  @sequence_number += 1
end

#replay_history(up_to: nil) ⇒ Object

Loads all events from the event stream of this instance and reprocesses them to get the current state of the aggregate.



55
56
57
58
59
60
61
# File 'lib/aggregates/aggregate_root.rb', line 55

def replay_history(up_to: nil)
  events = @event_stream.load_events
  events = events.select { |event| event.created_at <= up_to } if up_to.present?
  events.each do |event|
    process_event event
  end
end