Class: RubyEventStore::Projection

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby_event_store/projection.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(initial_state = nil, _internal: false) ⇒ Projection

Returns a new instance of Projection.



8
9
10
11
12
13
# File 'lib/ruby_event_store/projection.rb', line 8

def initialize(initial_state = nil, _internal: false)
  Deprecations.warn(:projection_new_constructor) unless _internal
  @handlers = {}
  @init = -> { initial_state }
  @streams = []
end

Class Method Details

.from_all_streamsObject



47
48
49
# File 'lib/ruby_event_store/projection.rb', line 47

def self.from_all_streams
  new(_internal: true)
end

.from_stream(stream_or_streams) ⇒ Object

Raises:

  • (ArgumentError)


39
40
41
42
43
44
45
# File 'lib/ruby_event_store/projection.rb', line 39

def self.from_stream(stream_or_streams)
  streams = Array(stream_or_streams)
  raise(ArgumentError, "At least one stream must be given") if streams.empty?
  projection = new(_internal: true)
  projection.instance_variable_set(:@streams, streams)
  projection
end

.init(initial_state = nil) ⇒ Object



15
16
17
# File 'lib/ruby_event_store/projection.rb', line 15

def self.init(initial_state = nil)
  new(initial_state, _internal: true)
end

Instance Method Details

#call(*scopes) ⇒ Object



31
32
33
34
35
36
37
# File 'lib/ruby_event_store/projection.rb', line 31

def call(*scopes)
  return initial_state if handled_events.empty?

  Deprecations.warn(:projection_multiple_scopes) if scopes.size > 1

  scopes.reduce(initial_state) { |state, scope| scope.of_type(handled_events).reduce(state, &method(:transition)) }
end

#init(handler) ⇒ Object



51
52
53
54
# File 'lib/ruby_event_store/projection.rb', line 51

def init(handler)
  @init = handler
  self
end

#on(*event_klasses, &block) ⇒ Object

Raises:

  • (ArgumentError)


19
20
21
22
23
24
25
26
27
28
29
# File 'lib/ruby_event_store/projection.rb', line 19

def on(*event_klasses, &block)
  raise(ArgumentError, "No handler block given") unless block_given?

  event_klasses.each do |event_klass|
    name = event_klass.to_s
    raise(ArgumentError, "Anonymous class is missing name") if name.start_with? ANONYMOUS_CLASS

    @handlers[name] = ->(state, event) { block.call(state, event) }
  end
  self
end

#run(event_store, start: nil, count: PAGE_SIZE) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/ruby_event_store/projection.rb', line 67

def run(event_store, start: nil, count: PAGE_SIZE)
  if @streams.any?
    raise ArgumentError, "Start must be an array with event ids" unless valid_start_for_streams?(start)
    scopes =
      @streams
        .zip(start || [])
        .map do |stream, start_event_id|
          scope = event_store.read.stream(stream).in_batches(count)
          scope = scope.from(start_event_id) if start_event_id
          scope
        end
  else
    raise ArgumentError, "Start must be valid event id" unless valid_start_for_all_streams?(start)
    scope = event_store.read.in_batches(count)
    scope = scope.from(start) if start
    scopes = [scope]
  end

  call(*scopes)
end

#when(events, handler) ⇒ Object



56
57
58
59
60
61
62
63
64
65
# File 'lib/ruby_event_store/projection.rb', line 56

def when(events, handler)
  Array(events).each do |event_klass|
    name = event_klass.to_s
    @handlers[name] = ->(state, event) do
      handler.call(state, event)
      state
    end
  end
  self
end