Class: FourthDimensional::AggregateRoot
- Inherits:
-
Object
- Object
- FourthDimensional::AggregateRoot
- Includes:
- Eventable
- Defined in:
- lib/fourth_dimensional/aggregate_root.rb
Overview
FourthDimensional::AggregateRoot
An aggregate root is an object whose entire state is built by applying events in sequential order.
Often you will see an aggregate root providing a method to create the event followed by a event binding to apply the changes to the current object.
class Post < FourthDimensional::AggregateRoot
attr_reader :state, :title
def initialize(*args)
super
@state = :draft
end
def add(title:)
apply PostAdded, data: { title: title }
end
def delete
apply PostDeleted
end
on PostAdded do |event|
@state = :added
@title = event.data.fetch('title')
end
on PostDeleted do |event|
@state = :deleted
end
end
aggregate = Post.new(id: SecureRandom.uuid)
aggregate.state # => :draft
aggregate.title # => nil
aggregate.add(title: 'post-title')
aggregate.state # => :added
aggregate.title # => 'post-title'
aggregate.delete
aggregate.state # => :deleted
Constant Summary collapse
- UnknownEventError =
Class.new(Error)
Instance Attribute Summary collapse
-
#applied_events ⇒ Object
readonly
array of events applied.
-
#id ⇒ Object
readonly
aggregate id.
-
#version ⇒ Object
readonly
current version.
Instance Method Summary collapse
-
#apply(event_class, **args) ⇒ Object
Applies an event to the aggregate when a callback is bound.
-
#apply_existing_event(event) ⇒ Object
Calls the event binding without persisting the event being applied.
-
#initialize(id:) ⇒ AggregateRoot
constructor
Initializes an aggregate with an id.
Methods included from Eventable
Constructor Details
#initialize(id:) ⇒ AggregateRoot
Initializes an aggregate with an id
62 63 64 65 66 67 |
# File 'lib/fourth_dimensional/aggregate_root.rb', line 62 def initialize(id:) @id = id @applied_events = [] @version = 1 end |
Instance Attribute Details
#applied_events ⇒ Object (readonly)
array of events applied
56 57 58 |
# File 'lib/fourth_dimensional/aggregate_root.rb', line 56 def applied_events @applied_events end |
#id ⇒ Object (readonly)
aggregate id
53 54 55 |
# File 'lib/fourth_dimensional/aggregate_root.rb', line 53 def id @id end |
#version ⇒ Object (readonly)
current version
59 60 61 |
# File 'lib/fourth_dimensional/aggregate_root.rb', line 59 def version @version end |
Instance Method Details
#apply(event_class, **args) ⇒ Object
Applies an event to the aggregate when a callback is bound. **args
are merged with the id
of the aggregate.
Callbacks are invoked within the instance of the aggregate root.
73 74 75 76 77 |
# File 'lib/fourth_dimensional/aggregate_root.rb', line 73 def apply(event_class, **args) event = event_class.new(args.merge(aggregate_id: id)) apply_existing_event(event) applied_events << event end |
#apply_existing_event(event) ⇒ Object
Calls the event binding without persisting the event being applied. Used when loading an aggregate from an existing store.
post.apply_existing_event(title_updated_event)
83 84 85 86 87 88 89 90 91 92 |
# File 'lib/fourth_dimensional/aggregate_root.rb', line 83 def apply_existing_event(event) callback = self.class.event_bindings[event.class] if callback.nil? raise UnknownEventError.new("#{self.class.name} doesn't have a binding for '#{event.class}'") end instance_exec(event, &callback) @version = next_version end |