Class: FourthDimensional::Repository

Inherits:
Object
  • Object
show all
Defined in:
lib/fourth_dimensional/repository.rb

Overview

FourthDimensional::Repository

Event sourcing is a good application for the repository pattern since we need to have a single source track commands and events being applied to the system.

The FourthDimensional::Repository is a wrapper around loading and persisting events/commands with dependency injection. This allows new repositories to be defined and easily registered.

The loading and persisting of events/commands are separated to allow separating the reading and writing databases should that become necessary.

class InMemoryEvents
  attr_reader :events

  def initialize
    @events = []
  end

  def self.instance
    @instance ||= InMemoryEvents.new
  end
end

class InMemoryEventLoader
  def for_aggregate(aggregate_id)
    InMemoryEvents.events
      .filter { |event| event.aggregate_id == aggregate_id }
  end

  def save_commands_and_events(commands:, events:)
    InMemoryEvents.events.concat(events)
  end
end

FourthDimensional.configure do |config|
  config.event_loader = InMemoryEventLoader.new
end

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(event_loader:) ⇒ Repository

Returns a new instance of Repository.



51
52
53
54
55
# File 'lib/fourth_dimensional/repository.rb', line 51

def initialize(event_loader:)
  @event_loader = event_loader
  @applied_events = []
  @called_commands = []
end

Instance Attribute Details

#applied_eventsObject (readonly)

An array of events saved



46
47
48
# File 'lib/fourth_dimensional/repository.rb', line 46

def applied_events
  @applied_events
end

#called_commandsObject (readonly)

An array of commands called



49
50
51
# File 'lib/fourth_dimensional/repository.rb', line 49

def called_commands
  @called_commands
end

#event_loaderObject (readonly)

The source to load events



43
44
45
# File 'lib/fourth_dimensional/repository.rb', line 43

def event_loader
  @event_loader
end

Instance Method Details

#events_for_aggregate(aggregate_id) ⇒ Object

Delegates to event_loader#for_aggregate

FourthDimensional.repository.events_for_aggregate(aggregate_id)


60
61
62
# File 'lib/fourth_dimensional/repository.rb', line 60

def events_for_aggregate(aggregate_id)
  event_loader.for_aggregate(aggregate_id)
end

#load_aggregate(aggregate_class, aggregate_id) ⇒ Object

Loads events from event_loader and applies them to a new instance of aggregate_class

FourthDimensional.repository.load_aggregate(PostAggregate, aggregate_id) # => PostAggregate


68
69
70
71
72
73
74
# File 'lib/fourth_dimensional/repository.rb', line 68

def load_aggregate(aggregate_class, aggregate_id)
  events_for_aggregate(aggregate_id)
    .reduce(aggregate_class.new(id: aggregate_id)) do |aggregate, event|
      aggregate.apply_existing_event(event)
      aggregate
    end
end

#save_command_and_events(command_and_events) ⇒ Object

Saves the command and events with the event_loader

repository.save_command_and_events(FourthDimensional::CommandHandler::CommandAndEvents.new(
  command: AddPost,
  events: [PostAdded]
))


82
83
84
85
# File 'lib/fourth_dimensional/repository.rb', line 82

def save_command_and_events(command_and_events)
  called_commands << command_and_events.command
  applied_events.concat(command_and_events.events)
end