sandthorn 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: d4f14306b2c1c46da7b99ce8409f6e69dcddf050
4
- data.tar.gz: 87dc839602892021e7aa13b2830bedbb1cc90891
2
+ SHA256:
3
+ metadata.gz: eb2833dc0d8dfa96bc80089a176f2718040f1107f0305232840e3009232511bb
4
+ data.tar.gz: 1c57a94df6798dfa32a1050d105bec05ccf30e08876c0a50aa610e3f7be3ce11
5
5
  SHA512:
6
- metadata.gz: 627da016b372e4f64e452c7bd3a6a8b69412f11e43b2f885e46b1aff6593d4cc73db78521761d5ef2f670ff238836b17a9e25d36208db37830670b38b30fea41
7
- data.tar.gz: a6db0ce8921f77bfeccf4fca94ba3ba2228f5f00d73318c445d5b3a60f9b8d7df98e3bfca6475bc27df9ff60a5704d3e51a0f46afeb8094bb0087bcd5a2b697a
6
+ metadata.gz: f21f398f4bbfc6ed3e23be70e294f5fbabfec60d1ed69bb03b8efd0f047d2131d9d225f4dd9794a24d45661ad6200b85364b54c50590825f0fa4bf9eb1d6759d
7
+ data.tar.gz: 027501a879da6025ffd51511e88b8affb9eb21e2e493086e143cab1faaa50e462142771a423a1e93f0d7b31f81da381869f7cfbebe5caf8a82880863c9ac9b4d
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in sandthorn.gemspec
4
- gemspec
4
+ gemspec
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  [![Build Status](https://travis-ci.org/Sandthorn/sandthorn.svg?branch=master)](https://travis-ci.org/Sandthorn/sandthorn)
2
- [![Coverage Status](https://coveralls.io/repos/Sandthorn/sandthorn/badge.png?branch=master)](https://coveralls.io/r/Sandthorn/sandthorn?branch=master)
3
- [![Code Climate](https://codeclimate.com/github/Sandthorn/sandthorn.png)](https://codeclimate.com/github/Sandthorn/sandthorn)
4
- [![Gem Version](https://badge.fury.io/rb/sandthorn.png)](http://badge.fury.io/rb/sandthorn)
2
+ [![Coverage Status](https://coveralls.io/repos/Sandthorn/sandthorn/badge.svg?branch=master)](https://coveralls.io/r/Sandthorn/sandthorn?branch=master)
3
+ [![Code Climate](https://codeclimate.com/github/Sandthorn/sandthorn.svg)](https://codeclimate.com/github/Sandthorn/sandthorn)
4
+ [![Gem Version](https://badge.fury.io/rb/sandthorn.svg)](http://badge.fury.io/rb/sandthorn)
5
5
 
6
6
  # Sandthorn Event Sourcing
7
7
  A ruby library for saving an object's state as a series of events.
@@ -124,7 +124,7 @@ class Board
124
124
  include Sandthorn::AggregateRoot
125
125
 
126
126
  # creates a private class method `board_created`
127
- contructor_events :board_created
127
+ constructor_events :board_created
128
128
 
129
129
  def self.create name
130
130
 
@@ -137,7 +137,7 @@ end
137
137
 
138
138
  ### `Sandthorn::AggregateRoot::stateless_events`
139
139
 
140
- Calling `stateless_events` creates public class methods. The first argument is an `aggregate_id` and the second argument is optional but has to be a hash and is stored in the attribute_deltas of the event.
140
+ Calling `stateless_events` creates public class methods. The first argument is an `aggregate_id` and the second argument is optional but has to be a hash and is stored in the event_data of the event.
141
141
 
142
142
  When creating a stateless event, the corresponding aggregate is never loaded and the event is saved without calling the save method.
143
143
 
@@ -1,6 +1,5 @@
1
1
  require "sandthorn/version"
2
2
  require "sandthorn/errors"
3
- require "sandthorn/event"
4
3
  require "sandthorn/aggregate_root"
5
4
  require "sandthorn/event_stores"
6
5
  require 'yaml'
@@ -118,6 +118,7 @@ module Sandthorn
118
118
  current_aggregate_version = events.last[:aggregate_version]
119
119
  aggregate.send :set_orginating_aggregate_version!, current_aggregate_version
120
120
  aggregate.send :set_current_aggregate_version!, current_aggregate_version
121
+ aggregate.send :set_aggregate_id, events.first.fetch(:aggregate_id)
121
122
  end
122
123
  attributes = build_instance_vars_from_events events
123
124
  aggregate.send :clear_aggregate_events
@@ -132,7 +133,7 @@ module Sandthorn
132
133
  def stateless_events(*event_names)
133
134
  event_names.each do |name|
134
135
  define_singleton_method name do |aggregate_id, *args|
135
- event = build_stateless_event(name.to_s, args)
136
+ event = build_stateless_event(aggregate_id, name.to_s, args)
136
137
  Sandthorn.save_events([event], aggregate_id, self)
137
138
  return aggregate_id
138
139
  end
@@ -169,24 +170,18 @@ module Sandthorn
169
170
 
170
171
  private
171
172
 
172
- def build_stateless_event name, args = []
173
+ def build_stateless_event aggregate_id, name, args = []
173
174
 
174
- formated_attribute_deltas = args.first.map do |key, value|
175
- {
176
- attribute_name: key.to_s,
177
- old_value: nil,
178
- new_value: value
179
- }
175
+ deltas = {}
176
+ args.first.each do |key, value|
177
+ deltas[key.to_sym] = { old_value: nil, new_value: value }
180
178
  end unless args.empty?
181
179
 
182
- data = {
183
- attribute_deltas: formated_attribute_deltas
184
- }
185
-
186
180
  return {
187
181
  aggregate_version: nil,
182
+ aggregate_id: aggregate_id,
188
183
  event_name: name,
189
- event_data: data,
184
+ event_data: deltas,
190
185
  event_metadata: nil
191
186
  }
192
187
 
@@ -194,11 +189,11 @@ module Sandthorn
194
189
 
195
190
  def build_instance_vars_from_events events
196
191
  events.each_with_object({}) do |event, instance_vars|
197
- event_data = event[:event_data]
198
- attribute_deltas = event_data[:attribute_deltas]
192
+ attribute_deltas = event[:event_data]
199
193
  unless attribute_deltas.nil?
200
- deltas = attribute_deltas.each_with_object({}) do |delta, acc|
201
- acc[delta[:attribute_name]] = delta[:new_value]
194
+ deltas = {}
195
+ attribute_deltas.each do |key, value|
196
+ deltas[key] = value[:new_value]
202
197
  end
203
198
  instance_vars.merge! deltas
204
199
  end
@@ -220,10 +215,7 @@ module Sandthorn
220
215
 
221
216
  def extract_relevant_aggregate_instance_variables
222
217
  instance_variables.select do |variable|
223
- equals_aggregate_id = variable.to_s == "@aggregate_id"
224
- does_not_contain_aggregate = !variable.to_s.start_with?("@aggregate_")
225
-
226
- equals_aggregate_id || does_not_contain_aggregate
218
+ !variable.to_s.start_with?("@aggregate_")
227
219
  end
228
220
  end
229
221
 
@@ -252,17 +244,13 @@ module Sandthorn
252
244
  end
253
245
 
254
246
  def commit_with_event_name(event_name)
255
- aggregate_attribute_deltas = get_delta
256
-
257
247
  increase_current_aggregate_version!
258
- data = {
259
- attribute_deltas: aggregate_attribute_deltas
260
- }
261
248
 
262
249
  @aggregate_events << ({
263
250
  aggregate_version: @aggregate_current_event_version,
251
+ aggregate_id: @aggregate_id,
264
252
  event_name: event_name,
265
- event_data: data,
253
+ event_data: get_delta(),
266
254
  event_metadata: @aggregate_trace_information
267
255
  })
268
256
 
@@ -3,7 +3,7 @@ module Sandthorn
3
3
  module Marshal
4
4
 
5
5
  def aggregate_initialize *args
6
- @aggregate_attribute_deltas = []
6
+ @aggregate_attribute_deltas = {}
7
7
  @aggregate_stored_instance_variables = {}
8
8
  end
9
9
 
@@ -20,7 +20,7 @@ module Sandthorn
20
20
  def get_delta
21
21
  deltas = extract_relevant_aggregate_instance_variables
22
22
  deltas.each { |d| delta_attribute(d) }
23
-
23
+
24
24
  result = @aggregate_attribute_deltas
25
25
  clear_aggregate_deltas
26
26
  result
@@ -42,8 +42,7 @@ module Sandthorn
42
42
  new_value_to_store = ::Marshal.load(new_dump)
43
43
  old_value_to_store = old_dump ? ::Marshal.load(old_dump) : nil
44
44
 
45
- @aggregate_attribute_deltas << {
46
- attribute_name: attribute_name.to_s.delete("@"),
45
+ @aggregate_attribute_deltas[attribute_name.to_s.delete("@").to_sym] = {
47
46
  old_value: old_value_to_store,
48
47
  new_value: new_value_to_store
49
48
  }
@@ -54,7 +53,7 @@ module Sandthorn
54
53
  end
55
54
 
56
55
  def clear_aggregate_deltas
57
- @aggregate_attribute_deltas = []
56
+ @aggregate_attribute_deltas = {}
58
57
  end
59
58
  end
60
59
  end
@@ -1,3 +1,3 @@
1
1
  module Sandthorn
2
- VERSION = "1.0.0"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.email = ["lars.krantz@alaz.se", "morgan.hallgren@gmail.com", "jesper.josefsson@gmail.com"]
11
11
  spec.description = %q{Event sourcing gem}
12
12
  spec.summary = %q{Event sourcing gem}
13
- spec.homepage = ""
13
+ spec.homepage = "https://github.com/Sandthorn/sandthorn"
14
14
  spec.license = "MIT"
15
15
 
16
16
  spec.files = `git ls-files`.split($/)
@@ -1,7 +1,5 @@
1
1
  require 'spec_helper'
2
2
 
3
-
4
-
5
3
  class PersonTest
6
4
  include Sandthorn::AggregateRoot
7
5
  attr_reader :name
@@ -44,15 +42,14 @@ describe 'Property Delta Event Sourcing' do
44
42
 
45
43
  it 'should be able to set name' do
46
44
  person.change_name "Klabbarparen"
47
- expect(person.name).to eql("Klabbarparen")
48
- #puts person.aggregate_events
45
+ expect(person.name).to eq("Klabbarparen")
49
46
  end
50
47
 
51
48
  it 'should be able to build from events' do
52
49
  person.change_name "Klabbarparen"
53
50
  builded = PersonTest.aggregate_build person.aggregate_events
54
- expect(builded.name).to eql(person.name)
55
- expect(builded.aggregate_id).to eql(person.aggregate_id)
51
+ expect(builded.name).to eq(person.name)
52
+ expect(builded.aggregate_id).to eq(person.aggregate_id)
56
53
  end
57
54
 
58
55
  it 'should not have any events when built up' do
@@ -75,16 +72,12 @@ describe 'Property Delta Event Sourcing' do
75
72
  person.add_to_hash :bar, "foo"
76
73
 
77
74
  builded = PersonTest.aggregate_build person.aggregate_events
78
- expect(builded.my_hash[:foo]).to eql("bar")
79
- expect(builded.my_hash[:bar]).to eql("foo")
75
+ expect(builded.my_hash[:foo]).to eq("bar")
76
+ expect(builded.my_hash[:bar]).to eq("foo")
80
77
 
81
78
  person.add_to_hash :foo, "BAR"
82
79
 
83
- #events = person.aggregate_events
84
- #events << builded.aggregate_events
85
- #puts events
86
-
87
80
  builded2 = PersonTest.aggregate_build person.aggregate_events
88
- expect(builded2.my_hash[:foo]).to eql("BAR")
81
+ expect(builded2.my_hash[:foo]).to eq("BAR")
89
82
  end
90
83
  end
@@ -44,7 +44,7 @@ module Sandthorn
44
44
  end
45
45
 
46
46
  it "should set the name instance variable" do
47
- expect(subject.name).to eql "new name"
47
+ expect(subject.name).to eq("new name")
48
48
  end
49
49
 
50
50
  it "should store the event params as methods args" do
@@ -52,11 +52,11 @@ module Sandthorn
52
52
  end
53
53
 
54
54
  it "should store the args to the event" do
55
- expect(subject.aggregate_events[1][:event_data][:attribute_deltas][0][:new_value]).to eql("new name")
55
+ expect(subject.aggregate_events[1][:event_data][:name][:new_value]).to eq("new name")
56
56
  end
57
57
 
58
58
  it "should store the event_name" do
59
- expect(subject.aggregate_events[1][:event_name]).to eql("name_changed")
59
+ expect(subject.aggregate_events[1][:event_name]).to eq("name_changed")
60
60
  end
61
61
  end
62
62
 
@@ -5,12 +5,12 @@ module Sandthorn
5
5
  class DirtyClass
6
6
  include Sandthorn::AggregateRoot
7
7
  attr_reader :name, :age
8
- attr :sex
8
+ attr :age
9
9
  attr_writer :writer
10
10
 
11
11
  def initialize args = {}
12
12
  @name = args.fetch(:name, nil)
13
- @sex = args.fetch(:sex, nil)
13
+ @age = args.fetch(:age, nil)
14
14
  @writer = args.fetch(:writer, nil)
15
15
  end
16
16
 
@@ -21,9 +21,9 @@ module Sandthorn
21
21
  end
22
22
  end
23
23
 
24
- def change_sex value
25
- unless sex == value
26
- @sex = value
24
+ def change_age value
25
+ unless age == value
26
+ @age = value
27
27
  commit
28
28
  end
29
29
  end
@@ -64,7 +64,7 @@ module Sandthorn
64
64
 
65
65
  context "all" do
66
66
  it "should all the aggregates" do
67
- expect(subject.length).to eql 3
67
+ expect(subject.length).to eq(3)
68
68
  end
69
69
 
70
70
  it "should include correct aggregates" do
@@ -83,10 +83,10 @@ module Sandthorn
83
83
 
84
84
  context "new with args" do
85
85
 
86
- let(:subject) { DirtyClass.new(name: "Mogge", sex: "hen", writer: true) }
86
+ let(:subject) { DirtyClass.new(name: "Mogge", age: 35, writer: true) }
87
87
  it "should set the values" do
88
- expect(subject.name).to eql "Mogge"
89
- expect(subject.sex).to eql "hen"
88
+ expect(subject.name).to eq("Mogge")
89
+ expect(subject.age).to eq(35)
90
90
  expect{subject.writer}.to raise_error NoMethodError
91
91
  end
92
92
  end
@@ -95,23 +95,23 @@ module Sandthorn
95
95
 
96
96
  it "should get new_name" do
97
97
  dirty_object.change_name "new_name"
98
- expect(dirty_object.name).to eql "new_name"
98
+ expect(dirty_object.name).to eq("new_name")
99
99
  end
100
100
 
101
101
  it "should generate one event on new" do
102
- expect(dirty_object.aggregate_events.length).to eql 1
102
+ expect(dirty_object.aggregate_events.length).to eq(1)
103
103
  end
104
104
 
105
105
  it "should generate 2 events new and change_name" do
106
106
  dirty_object.change_name "new_name"
107
- expect(dirty_object.aggregate_events.length).to eql 2
107
+ expect(dirty_object.aggregate_events.length).to eq(2)
108
108
  end
109
109
  end
110
110
 
111
- context "when changing sex (attr)" do
112
- it "should get new_sex" do
113
- dirty_object.change_sex "new_sex"
114
- expect(dirty_object.sex).to eql "new_sex"
111
+ context "when changing age (attr)" do
112
+ it "should get new_age" do
113
+ dirty_object.change_age "new_age"
114
+ expect(dirty_object.age).to eq("new_age")
115
115
  end
116
116
  end
117
117
 
@@ -123,27 +123,27 @@ module Sandthorn
123
123
 
124
124
  context "save" do
125
125
  it "should not have events on aggregate after save" do
126
- expect(dirty_object.save.aggregate_events.length).to eql 0
126
+ expect(dirty_object.save.aggregate_events.length).to eq(0)
127
127
  end
128
128
 
129
129
  it "should have aggregate_originating_version == 0 pre save" do
130
- expect(dirty_object.aggregate_originating_version).to eql 0
130
+ expect(dirty_object.aggregate_originating_version).to eq(0)
131
131
  end
132
132
 
133
133
  it "should have aggregate_originating_version == 1 post save" do
134
- expect(dirty_object.save.aggregate_originating_version).to eql 1
134
+ expect(dirty_object.save.aggregate_originating_version).to eq(1)
135
135
  end
136
136
  end
137
137
 
138
138
  context "find" do
139
139
  before(:each) { dirty_object.save }
140
140
  it "should find by id" do
141
- expect(DirtyClass.find(dirty_object.id).id).to eql dirty_object.id
141
+ expect(DirtyClass.find(dirty_object.id).id).to eq(dirty_object.id)
142
142
  end
143
143
 
144
144
  it "should hold changed name" do
145
145
  dirty_object.change_name("morgan").save
146
- expect(DirtyClass.find(dirty_object.id).name).to eql "morgan"
146
+ expect(DirtyClass.find(dirty_object.id).name).to eq("morgan")
147
147
  end
148
148
 
149
149
  it "should raise error if trying to find id that not exist" do
@@ -157,7 +157,7 @@ module Sandthorn
157
157
  describe "event data" do
158
158
 
159
159
  let(:dirty_object) {
160
- o = DirtyClass.new :name => "old_value", :sex => "hen"
160
+ o = DirtyClass.new :name => "old_value", :age => 35
161
161
  o.save
162
162
  }
163
163
 
@@ -167,7 +167,7 @@ module Sandthorn
167
167
 
168
168
  it "should set the old_value on the event" do
169
169
  dirty_object_after_find.change_name "new_name"
170
- expect(dirty_object_after_find.aggregate_events.last[:event_data][:attribute_deltas].first[:old_value]).to eql "old_value"
170
+ expect(dirty_object_after_find.aggregate_events.last[:event_data][:name][:old_value]).to eq("old_value")
171
171
  end
172
172
 
173
173
  end
@@ -176,36 +176,32 @@ module Sandthorn
176
176
 
177
177
  it "should set the old_value on the event" do
178
178
  dirty_object.change_name "new_name"
179
- expect(dirty_object.aggregate_events.last[:event_data][:attribute_deltas].first[:old_value]).to eql "old_value"
179
+ expect(dirty_object.aggregate_events.last[:event_data][:name][:old_value]).to eq("old_value")
180
180
  end
181
181
 
182
182
  it "should not change aggregate_id" do
183
183
  dirty_object.change_name "new_name"
184
- expect(dirty_object.aggregate_events.last[:event_data][:attribute_deltas].last[:attribute_name]).not_to eql "aggregate_id"
184
+ expect(dirty_object.aggregate_events.last[:event_data]["attribute_name"]).not_to eq("aggregate_id")
185
185
  end
186
186
 
187
- it "should not change sex attribute if sex method is not runned" do
187
+ it "should not change age attribute if age method is not runned" do
188
188
  dirty_object.change_name "new_name"
189
189
  dirty_object.aggregate_events.each do |event|
190
- event[:event_data][:attribute_deltas].each do |attribute_delta|
191
- expect(attribute_delta[:attribute_name]).not_to eql "sex"
192
- end
190
+ expect(event[:event_data]["age"].nil?).to be_truthy
193
191
  end
194
192
  end
195
193
 
196
- it "should not change sex attribute if sex attribute is the same" do
197
- dirty_object.change_sex "hen"
194
+ it "should not change age attribute if age attribute is the same" do
195
+ dirty_object.change_age 35
198
196
  dirty_object.aggregate_events.each do |event|
199
- event[:event_data][:attribute_deltas].each do |attribute_delta|
200
- expect(attribute_delta[:attribute_name]).not_to eql "sex"
201
- end
197
+ expect(event[:event_data]["age"].nil?).to be_truthy
202
198
  end
203
199
  end
204
200
 
205
- it "should set old_value and new_value on sex change" do
206
- dirty_object.change_sex "shemale"
207
- expect(dirty_object.aggregate_events.last[:event_data][:attribute_deltas].first[:old_value]).to eql "hen"
208
- expect(dirty_object.aggregate_events.last[:event_data][:attribute_deltas].first[:new_value]).to eql "shemale"
201
+ it "should set old_value and new_value on age change" do
202
+ dirty_object.change_age 36
203
+ expect(dirty_object.aggregate_events.last[:event_data][:age][:old_value]).to eq(35)
204
+ expect(dirty_object.aggregate_events.last[:event_data][:age][:new_value]).to eq(36)
209
205
  end
210
206
  end
211
207
  end
@@ -218,11 +214,11 @@ module Sandthorn
218
214
  end
219
215
 
220
216
  it "should have the event no_state_change_only_empty_event" do
221
- expect(dirty_object.aggregate_events.first[:event_name]).to eql("no_state_change_only_empty_event")
217
+ expect(dirty_object.aggregate_events.first[:event_name]).to eq("no_state_change_only_empty_event")
222
218
  end
223
219
 
224
- it "should have attribute_deltas set to empty array" do
225
- expect(dirty_object.aggregate_events.first[:event_data][:attribute_deltas]).to eql([])
220
+ it "should have event_data set to empty hash" do
221
+ expect(dirty_object.aggregate_events.first[:event_data]).to eq({})
226
222
  end
227
223
 
228
224
  end