-
Notifications
You must be signed in to change notification settings - Fork 124
/
Copy pathaggregate_root.rb
106 lines (89 loc) · 2.49 KB
/
aggregate_root.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# frozen_string_literal: true
require_relative "aggregate_root/version"
require_relative "aggregate_root/default_apply_strategy"
require_relative "aggregate_root/repository"
require_relative "aggregate_root/instrumented_repository"
require_relative "aggregate_root/instrumented_apply_strategy"
require_relative "aggregate_root/snapshot_repository"
module AggregateRoot
module OnDSL
def on(*event_klasses, &block)
event_klasses.each do |event_klass|
name = event_klass.to_s
handler_name = "on_#{name}"
define_method(handler_name, &block)
@on_methods ||= {}
@on_methods[name] = handler_name
private(handler_name)
end
end
def on_methods
@on_methods ||= {}
(superclass.respond_to?(:on_methods) ? superclass.on_methods : {}).merge(@on_methods)
end
end
module Constructor
def new(*, **)
super.tap do |instance|
instance.instance_variable_set(:@version, -1)
instance.instance_variable_set(:@unpublished_events, [])
end
end
end
module AggregateMethods
def apply(*events)
events.each do |event|
apply_strategy.(self, event)
@unpublished_events << event
end
end
def version
@version
end
def version=(value)
@unpublished_events = []
@version = value
end
def unpublished_events
@unpublished_events.each
end
UNMARSHALED_VARIABLES = [:@version, :@unpublished_events]
def marshal_dump
instance_variables.reject{|m| UNMARSHALED_VARIABLES.include? m}.inject({}) do |vars, attr|
vars[attr] = instance_variable_get(attr)
vars
end
end
def marshal_load(vars)
vars.each do |attr, value|
instance_variable_set(attr, value) unless UNMARSHALED_VARIABLES.include?(attr)
end
end
end
def self.with_default_strategy(strict: true)
Module.new do
def self.included(host_class)
host_class.extend OnDSL
host_class.extend Constructor
host_class.include AggregateMethods
end
define_method :apply_strategy do
DefaultApplyStrategy.new(strict: strict)
end
end
end
def self.with_strategy(strategy)
Module.new do
def self.included(host_class)
host_class.extend Constructor
host_class.include AggregateMethods
end
define_method :apply_strategy do
strategy.call
end
end
end
def self.included(host_class)
host_class.include with_default_strategy
end
end