sandthorn 0.5.1 → 0.6.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
2
  SHA1:
3
- metadata.gz: 974b2f1521c09c03ea633790cdc1de37b47b46fb
4
- data.tar.gz: 782de64f891f07fc78aff62cd53ebd70b9f05846
3
+ metadata.gz: f39fd41916e13c8d9af482497da9774295644984
4
+ data.tar.gz: b3ae469f87f318a99d27f34049513cf35cae754d
5
5
  SHA512:
6
- metadata.gz: 9fc7334244668d45c4a39e730ab51dadb468267839638fe299b6c4ea131c964078d9dd2e73cfdd0fe23297ebfc257e7dfb6bab715f3a07996478c1d052f4de67
7
- data.tar.gz: 86b770a90624c2cfed0a1ae9cae04f07f569c7ed3fb75c297cd5a53a9573180d1888b7f57ea3b39754f5c448bb8da7752e411e6f60346d19a168dc72a79e3d78
6
+ metadata.gz: 2c3d769b134a6421cfe4164190726c9ce1448f06962ee24aee7aec32f14fc1cf7c4c6e5c2a6160c62a0c316f482e8d72709463c2ac3f0298e7584ab02f604011
7
+ data.tar.gz: d54a6d161c31dd38ff4bd03217035d35d2f445419d83c59caca649828b32543eaf9714ed8832b56f4262315fad95992936b778bdda52f602254103611067b6c2
data/.gitignore CHANGED
@@ -17,3 +17,4 @@ tmp
17
17
  .yardoc
18
18
  _yardoc
19
19
  doc/
20
+ .idea
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sandthorn (0.5.1)
4
+ sandthorn (0.6.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -9,7 +9,7 @@ GEM
9
9
  autotest-standalone (4.5.11)
10
10
  awesome_print (1.2.0)
11
11
  coderay (1.1.0)
12
- coveralls (0.7.0)
12
+ coveralls (0.7.1)
13
13
  multi_json (~> 1.3)
14
14
  rest-client
15
15
  simplecov (>= 0.7)
@@ -19,11 +19,11 @@ GEM
19
19
  docile (1.1.5)
20
20
  gem-release (0.7.3)
21
21
  method_source (0.8.2)
22
- mime-types (2.3)
22
+ mime-types (2.4.3)
23
23
  multi_json (1.10.1)
24
- netrc (0.7.7)
24
+ netrc (0.8.0)
25
25
  pg (0.17.1)
26
- pry (0.10.0)
26
+ pry (0.10.1)
27
27
  coderay (~> 1.1.0)
28
28
  method_source (~> 0.8.1)
29
29
  slop (~> 3.4)
@@ -34,25 +34,25 @@ GEM
34
34
  rest-client (1.7.2)
35
35
  mime-types (>= 1.16, < 3.0)
36
36
  netrc (~> 0.7)
37
- rspec (3.0.0)
38
- rspec-core (~> 3.0.0)
39
- rspec-expectations (~> 3.0.0)
40
- rspec-mocks (~> 3.0.0)
41
- rspec-core (3.0.3)
42
- rspec-support (~> 3.0.0)
43
- rspec-expectations (3.0.3)
37
+ rspec (3.1.0)
38
+ rspec-core (~> 3.1.0)
39
+ rspec-expectations (~> 3.1.0)
40
+ rspec-mocks (~> 3.1.0)
41
+ rspec-core (3.1.7)
42
+ rspec-support (~> 3.1.0)
43
+ rspec-expectations (3.1.2)
44
44
  diff-lcs (>= 1.2.0, < 2.0)
45
- rspec-support (~> 3.0.0)
46
- rspec-mocks (3.0.3)
47
- rspec-support (~> 3.0.0)
48
- rspec-support (3.0.3)
45
+ rspec-support (~> 3.1.0)
46
+ rspec-mocks (3.1.3)
47
+ rspec-support (~> 3.1.0)
48
+ rspec-support (3.1.2)
49
49
  sandthorn_driver_sequel (1.1.0)
50
50
  pg
51
51
  sequel
52
- sequel (4.13.0)
53
- simplecov (0.9.0)
52
+ sequel (4.15.0)
53
+ simplecov (0.9.1)
54
54
  docile (~> 1.1.0)
55
- multi_json
55
+ multi_json (~> 1.0)
56
56
  simplecov-html (~> 0.8.0)
57
57
  simplecov-html (0.8.0)
58
58
  slop (3.6.0)
@@ -60,7 +60,7 @@ GEM
60
60
  term-ansicolor (1.3.0)
61
61
  tins (~> 1.0)
62
62
  thor (0.19.1)
63
- tins (1.3.0)
63
+ tins (1.3.3)
64
64
  yard (0.8.7.4)
65
65
 
66
66
  PLATFORMS
@@ -75,7 +75,7 @@ DEPENDENCIES
75
75
  pry
76
76
  pry-doc
77
77
  rake
78
- rspec
78
+ rspec (~> 3.0)
79
79
  sandthorn!
80
80
  sandthorn_driver_sequel (~> 1.1)
81
81
  sqlite3
data/README.md CHANGED
@@ -64,10 +64,30 @@ class Ship
64
64
  end
65
65
  end
66
66
 
67
- # Setup the framework with the sequel driver for persistance
67
+ # Configure a driver
68
68
  url = "sqlite://spec/db/sequel_driver.sqlite3"
69
- catch_all_config = [ { driver: SandthornDriverSequel.driver_from_url(url: url) } ]
70
- Sandthorn.configuration = catch_all_config
69
+ sql_event_store = SandthornDriverSequel.driver_from_url(url: url)
70
+ Sandthorn.configure do |c|
71
+ c.event_store = sql_event_store
72
+ end
73
+
74
+ # Or configure many drivers
75
+
76
+ Sandthorn.configure do |c|
77
+ c.event_stores = {
78
+ default: sql_event_store,
79
+ other_event_store: other_store
80
+ }
81
+ end
82
+
83
+ # Assign your aggregates to a named event store
84
+
85
+ class Boat
86
+ include Sandthorn::AggregateRoot
87
+ event_store :other_event_store
88
+ end
89
+
90
+ # Aggregates with no explicit event store will use the default event store
71
91
 
72
92
  # Migrate db schema for the sequel driver
73
93
  migrator = SandthornDriverSequel::Migration.new url: url
data/lib/sandthorn.rb CHANGED
@@ -1,16 +1,30 @@
1
1
  require "sandthorn/version"
2
2
  require "sandthorn/errors"
3
3
  require "sandthorn/aggregate_root"
4
+ require "sandthorn/event_stores"
4
5
  require 'yaml'
5
6
  require 'securerandom'
6
7
 
7
8
  module Sandthorn
8
9
  class << self
9
- def configuration= configuration
10
- @configuration = configuration
10
+ extend Forwardable
11
+
12
+ def_delegators :configuration, :event_stores
13
+
14
+ def default_event_store
15
+ event_stores.default_store
16
+ end
17
+
18
+ def default_event_store=(store)
19
+ event_stores.default_store = store
20
+ end
21
+
22
+ def configure
23
+ yield(configuration) if block_given?
11
24
  end
25
+
12
26
  def configuration
13
- @configuration ||= []
27
+ @configuration ||= Configuration.new
14
28
  end
15
29
 
16
30
  def serialize data
@@ -31,35 +45,29 @@ module Sandthorn
31
45
  SecureRandom.uuid
32
46
  end
33
47
 
34
- def get_aggregate_events aggregate_id, class_name
35
- driver_for(class_name).get_aggregate_events aggregate_id, class_name
48
+ def get_aggregate_events aggregate_id, aggregate_type
49
+ event_store_for(aggregate_type).get_aggregate_events aggregate_id, aggregate_type
36
50
  end
37
51
 
38
- def save_events aggregate_events, originating_aggregate_version, aggregate_id, class_name
39
- #begin
40
- driver_for(class_name).save_events aggregate_events, originating_aggregate_version, aggregate_id, *class_name
41
- #rescue UpptecEventSequelDriver::Errors::WrongAggregateVersionError => sequel_error
42
- # raise UpptecEventFramework::Errors::ConcurrencyError.new sequel_error.message
43
- #end
52
+ def save_events aggregate_events, originating_aggregate_version, aggregate_id, aggregate_type
53
+ event_store_for(aggregate_type).save_events aggregate_events, originating_aggregate_version, aggregate_id, *aggregate_type
44
54
  end
45
55
 
46
- def get_aggregate aggregate_id, class_name
47
- driver_for(class_name).get_aggregate aggregate_id, class_name
56
+ def get_aggregate aggregate_id, aggregate_type
57
+ event_store_for(aggregate_type).get_aggregate aggregate_id, aggregate_type
48
58
  end
49
59
 
50
- def save_snapshot aggregate_snapshot, aggregate_id, class_name
51
- driver_for(class_name).save_snapshot aggregate_snapshot, aggregate_id, class_name
60
+ def save_snapshot aggregate_snapshot, aggregate_id, aggregate_type
61
+ event_store_for(aggregate_type).save_snapshot aggregate_snapshot, aggregate_id, aggregate_type
52
62
  end
53
63
 
54
- def get_aggregate_list_by_typename class_name
55
- driver_for(class_name).get_aggregate_list_by_typename class_name
64
+ def get_aggregate_list_by_type aggregate_type
65
+ event_store_for(aggregate_type).get_aggregate_list_by_typename aggregate_type
56
66
  end
57
67
 
58
- def get_events aggregate_types: [], take: 0, after_sequence_number: 0
59
- drivers = drivers_for_aggregate_types type_names: aggregate_types
60
- raise Sandthorn::Errors::Error.new "Cannot get events from multiple contexts simultaneously, only one single context can be handled at a time." unless drivers.length == 1
61
- driver = drivers.first
62
- events = driver.get_events aggregate_types: aggregate_types, take: take, after_sequence_number: after_sequence_number
68
+ def get_events event_store: :default, aggregate_types: [], take: 0, after_sequence_number: 0
69
+ event_store = find_event_store(event_store)
70
+ events = event_store.get_events aggregate_types: aggregate_types, take: take, after_sequence_number: after_sequence_number
63
71
  events.each do |event|
64
72
  event[:event_args] = deserialize event[:event_data]
65
73
  event.delete(:event_data)
@@ -68,43 +76,44 @@ module Sandthorn
68
76
  end
69
77
 
70
78
  def obsolete_snapshots type_names: [], min_event_distance: 0
71
- drivers = drivers_for_aggregate_types type_names: type_names
72
- obsolete = drivers.flat_map { |driver| driver.obsolete_snapshots(class_names: type_names, max_event_distance: min_event_distance) }
73
- yielder = []
74
- obsolete.each do |single_obsolete|
75
- type = Kernel.const_get single_obsolete[:aggregate_type]
76
- aggregate = type.aggregate_find single_obsolete[:aggregate_id]
77
- if block_given?
78
- yield aggregate
79
- else
80
- yielder << aggregate
81
- end
79
+ obsolete = event_stores.flat_map { |event_store| event_store.obsolete_snapshots(class_names: type_names, max_event_distance: min_event_distance) }
80
+ obsolete.map do |single_obsolete|
81
+ type = Kernel.const_get single_obsolete[:aggregate_type]
82
+ aggregate = type.aggregate_find(single_obsolete[:aggregate_id]).tap do |agg|
83
+ yield agg if block_given?
84
+ end
82
85
  end
83
- yielder unless block_given?
86
+ end
87
+
88
+ def find_event_store(name)
89
+ event_stores.by_name(name)
84
90
  end
85
91
 
86
92
  private
87
- def driver_for class_name, &block
88
- driver = identify_driver_from_class class_name
89
- block.call(driver) if block_given?
90
- driver
91
- end
92
- def identify_driver_from_class class_name
93
- matches = configuration.select do |conf|
94
- r = Regexp.new "^#{conf[:aggregate_pattern]}"
95
- pattern = class_name.to_s
96
- conf[:aggregate_pattern].nil? || r.match(pattern)
93
+
94
+ def event_store_for(aggregate_type)
95
+ event_store = event_stores.by_name(aggregate_type.event_store).tap do |store|
96
+ yield(store) if block_given?
97
97
  end
98
- raise Sandthorn::Errors::ConfigurationError.new "Aggregate class #{class_name} is not configured for Sandthorn" if matches.empty?
99
- first_match = matches.first
100
- first_match[:driver]
101
98
  end
102
- def drivers_for_aggregate_types type_names: []
103
- return all_drivers if type_names.empty?
104
- type_names.map { |e| driver_for e }
105
- end
106
- def all_drivers
107
- configuration.map { |e| e[:driver] }
99
+
100
+ class Configuration
101
+ extend Forwardable
102
+
103
+ def_delegators :default_store, :event_stores, :default_store=
104
+
105
+ def initialize
106
+ yield(self) if block_given?
107
+ end
108
+
109
+ def event_stores
110
+ @event_stores ||= EventStores.new
111
+ end
112
+
113
+ def event_store=(store)
114
+ @event_stores = EventStores.new(store)
115
+ end
116
+ alias_method :event_stores=, :event_store=
108
117
  end
109
118
  end
110
119
  end
@@ -29,9 +29,8 @@ module Sandthorn
29
29
  aggregate_events,
30
30
  aggregate_originating_version,
31
31
  aggregate_id,
32
- self.class.name
32
+ self.class
33
33
  )
34
-
35
34
  @aggregate_events = []
36
35
  @aggregate_originating_version = @aggregate_current_event_version
37
36
  end
@@ -39,6 +38,10 @@ module Sandthorn
39
38
  self
40
39
  end
41
40
 
41
+ def ==(other)
42
+ other.respond_to?(:aggregate_id) && aggregate_id == other.aggregate_id
43
+ end
44
+
42
45
  def aggregate_trace args
43
46
  @aggregate_trace_information = args
44
47
  yield self if block_given?
@@ -83,8 +86,16 @@ module Sandthorn
83
86
  @@aggregate_trace_information = nil
84
87
  end
85
88
 
89
+ def event_store(event_store = nil)
90
+ if event_store
91
+ @event_store = event_store
92
+ else
93
+ @event_store
94
+ end
95
+ end
96
+
86
97
  def all
87
- aggregate_id_list = Sandthorn.get_aggregate_list_by_typename(self.name)
98
+ aggregate_id_list = Sandthorn.get_aggregate_list_by_type(self)
88
99
  find aggregate_id_list
89
100
  end
90
101
 
@@ -94,17 +105,13 @@ module Sandthorn
94
105
  end
95
106
 
96
107
  def aggregate_find aggregate_id
97
- class_name = self.respond_to?(:name) ? self.name : self.class # to be able to extend a string for example.
98
- events = Sandthorn.get_aggregate(aggregate_id, class_name)
99
-
100
- unless events and !events.empty?
108
+ events = Sandthorn.get_aggregate(aggregate_id, self)
109
+ unless events && !events.empty?
101
110
  raise Sandthorn::Errors::AggregateNotFound
102
111
  end
103
-
104
112
  transformed_events = events.map do |e|
105
113
  e.merge(event_args: Sandthorn.deserialize(e[:event_data]))
106
114
  end
107
-
108
115
  aggregate_build transformed_events
109
116
  end
110
117
 
@@ -128,7 +135,7 @@ module Sandthorn
128
135
  current_aggregate_version = aggregate.aggregate_originating_version
129
136
  events.shift
130
137
  else
131
- aggregate = start_build_from_new events
138
+ aggregate = create_new_empty_aggregate
132
139
  end
133
140
 
134
141
  attributes = build_instance_vars_from_events events
@@ -165,17 +172,8 @@ module Sandthorn
165
172
  snapshot = events.first[:event_args][0]
166
173
  end
167
174
 
168
- def start_build_from_new events
169
- new_args = events.first[:event_args][:method_args]
170
-
171
- if new_args.nil?
172
- aggregate = new
173
- else
174
- aggregate = new(*new_args)
175
- end
176
-
177
- aggregate.send :aggregate_clear_current_event_version!
178
- aggregate
175
+ def create_new_empty_aggregate
176
+ allocate
179
177
  end
180
178
  end
181
179
 
@@ -25,6 +25,20 @@ module Sandthorn
25
25
  unless aggregate_snapshot
26
26
  raise Errors::SnapshotError, "No snapshot has been created!"
27
27
  end
28
+ @aggregate_snapshot[:event_data] = Sandthorn.serialize @aggregate_snapshot[:event_args]
29
+ @aggregate_snapshot[:event_args] = nil
30
+ Sandthorn.save_snapshot @aggregate_snapshot, @aggregate_id, self.class
31
+ @aggregate_snapshot = nil
32
+ end
33
+ private
34
+ def aggregate_create_event_when_extended
35
+ self.aggregate_snapshot!
36
+ vars = extract_relevant_aggregate_instance_variables
37
+ vars.each do |var_name|
38
+ value = instance_variable_get var_name
39
+ dump = Marshal.dump(value)
40
+ store_aggregate_instance_variable var_name, dump
41
+ end
28
42
 
29
43
  @aggregate_snapshot[:event_data] = Sandthorn
30
44
  .serialize aggregate_snapshot[:event_args]
@@ -0,0 +1,64 @@
1
+ require 'forwardable'
2
+
3
+ module Sandthorn
4
+ class EventStores
5
+ extend Forwardable
6
+ include Enumerable
7
+
8
+ def_delegators :stores, :each
9
+
10
+ def initialize(stores = nil)
11
+ @store_map = Hash.new
12
+ add_initial(stores)
13
+ end
14
+
15
+ def add(name, event_store)
16
+ store_map[name] = event_store
17
+ end
18
+ alias_method :[]=, :add
19
+
20
+ def add_many(stores)
21
+ stores.each_pair do |name, store|
22
+ add(name, store)
23
+ end
24
+ end
25
+
26
+ def by_name(name)
27
+ store_map[name] || default_store
28
+ end
29
+ alias_method :[], :by_name
30
+
31
+ def default_store
32
+ store_map.fetch(:default)
33
+ end
34
+
35
+ def default_store=(store)
36
+ store_map[:default] = store
37
+ end
38
+
39
+ def stores
40
+ store_map.values
41
+ end
42
+
43
+ private
44
+
45
+ attr_reader :store_map
46
+
47
+ def add_initial(store)
48
+ if is_event_store?(store)
49
+ self.default_store = store
50
+ elsif is_many_event_stores?(store)
51
+ add_many(store)
52
+ end
53
+ end
54
+
55
+ def is_many_event_stores?(store)
56
+ store.respond_to?(:each_pair)
57
+ end
58
+
59
+ def is_event_store?(store)
60
+ store.respond_to?(:get_events)
61
+ end
62
+
63
+ end
64
+ end
@@ -1,3 +1,3 @@
1
1
  module Sandthorn
2
- VERSION = "0.5.1"
2
+ VERSION = "0.6.0"
3
3
  end
data/sandthorn.gemspec CHANGED
@@ -21,7 +21,7 @@ Gem::Specification.new do |spec|
21
21
 
22
22
  spec.add_development_dependency "bundler", "~> 1.3"
23
23
  spec.add_development_dependency "rake"
24
- spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "rspec", "~> 3.0"
25
25
  spec.add_development_dependency "gem-release"
26
26
  spec.add_development_dependency "pry"
27
27
  spec.add_development_dependency "pry-doc"
@@ -38,6 +38,17 @@ module Sandthorn
38
38
 
39
39
  end
40
40
 
41
+ describe "::event_store" do
42
+ let(:klass) { Class.new { include Sandthorn::AggregateRoot } }
43
+ it "is available as a class method" do
44
+ expect(klass).to respond_to(:event_store)
45
+ end
46
+ it "sets the event store as a class level variable and returns it" do
47
+ klass.event_store(:other)
48
+ expect(klass.event_store).to eq(:other)
49
+ end
50
+ end
51
+
41
52
  describe "when get all aggregates from DirtyClass" do
42
53
 
43
54
  before(:each) do
@@ -72,4 +72,4 @@ describe 'when using complex types in events' do
72
72
  builded = IAmComplex.aggregate_build aggr.aggregate_events
73
73
  expect(builded.hello.foo_bar).to eql "morgan"
74
74
  end
75
- end
75
+ end
@@ -0,0 +1,81 @@
1
+ require 'spec_helper'
2
+
3
+ module Sandthorn
4
+ describe EventStores do
5
+ let(:stores) { EventStores.new }
6
+
7
+ describe "#initialize" do
8
+ context "when given a single event_store" do
9
+ it "sets it as the default event store" do
10
+ store = double(get_events: true)
11
+ allow(store).to receive(:get_events)
12
+ stores = EventStores.new(store)
13
+ expect(stores.default_store).to eq(store)
14
+ end
15
+ end
16
+
17
+ context "when given number of stores" do
18
+ it "adds them all" do
19
+ stores = {
20
+ default: double,
21
+ other: double
22
+ }
23
+ repo = EventStores.new(stores)
24
+ expect(repo.by_name(:default)).to eq(stores[:default])
25
+ expect(repo.by_name(:other)).to eq(stores[:other])
26
+ end
27
+ end
28
+ end
29
+
30
+ describe "enumerable" do
31
+ let(:store) { double }
32
+ let(:other_store) { double }
33
+ it "should respond to each" do
34
+ expect(stores).to respond_to(:each)
35
+ end
36
+
37
+ it "should yield each store" do
38
+ stores.add_many(
39
+ foo: store,
40
+ bar: other_store
41
+ )
42
+ expect { |block| stores.each(&block) }.to yield_successive_args(store, other_store)
43
+ end
44
+ end
45
+
46
+ describe "#default_store=" do
47
+ it "sets the default" do
48
+ store = double
49
+ stores = EventStores.new
50
+ stores.default_store = store
51
+ expect(stores.default_store).to eq(store)
52
+ end
53
+ end
54
+
55
+ describe "#by_name" do
56
+ context "when the store exists" do
57
+ it "returns the store" do
58
+ store = double
59
+ stores.add(:foo, store)
60
+ expect(stores.by_name(:foo)).to eq(store)
61
+ end
62
+ end
63
+
64
+ context "when the store does not exist" do
65
+ it "returns the default store" do
66
+ store = double
67
+ stores.default_store = store
68
+ expect(stores.by_name(:unknown)).to eq(store)
69
+ end
70
+ end
71
+ end
72
+
73
+ describe "#add" do
74
+ it "adds the store under the given name" do
75
+ store = double
76
+ stores.add(:foo, store)
77
+ expect(stores[:foo]).to eq(store)
78
+ end
79
+ end
80
+ end
81
+ end
@@ -4,12 +4,70 @@ class AnAggregate
4
4
  include Sandthorn::AggregateRoot
5
5
  end
6
6
 
7
+ class AnotherAggregate
8
+ include Sandthorn::AggregateRoot
9
+ event_store :other
10
+ end
11
+
7
12
  describe Sandthorn do
8
- before(:each) { AnAggregate.new.save }
9
- let(:events) { Sandthorn.get_events aggregate_types: [AnAggregate] }
10
- context "when getting events using Sandthorn.get_events for an aggregate type" do
11
- it "should return raw events" do
12
- expect(events).to_not be_empty
13
- end
14
- end
13
+
14
+ describe "::get_events" do
15
+ context "when getting events using Sandthorn.get_events for an aggregate type" do
16
+ before do
17
+ AnAggregate.new.save
18
+ end
19
+ let(:events) { Sandthorn.get_events aggregate_types: [AnAggregate] }
20
+ it "should return events" do
21
+ expect(events).to_not be_empty
22
+ end
23
+ end
24
+
25
+ context "when there are many event stores configured" do
26
+ before do
27
+ setup_secondary_db
28
+ end
29
+
30
+ let!(:agg) do
31
+ AnAggregate.new.save
32
+ end
33
+
34
+ let!(:other_agg) do
35
+ AnotherAggregate.new.save
36
+ end
37
+
38
+ shared_examples(:default_event_store) do
39
+ it "returns events from the default event store" do
40
+ events = Sandthorn.get_events
41
+ expect(events).to all(have_aggregate_type("AnAggregate"))
42
+ end
43
+ end
44
+
45
+ context "when no explicit event store is used" do
46
+ it_behaves_like :default_event_store
47
+ end
48
+
49
+ context "when given an explicit event store" do
50
+ context "and that event store exists" do
51
+ it "returns events from the chosen event store" do
52
+ events = Sandthorn.get_events(event_store: :other)
53
+ expect(events).to all(have_aggregate_type("AnotherAggregate"))
54
+ end
55
+ end
56
+
57
+ context "and that event store does not exist" do
58
+ it_behaves_like :default_event_store
59
+ end
60
+ end
61
+
62
+ end
63
+ end
64
+
65
+ def setup_secondary_db
66
+ url = "sqlite://spec/db/other_db.sqlite3"
67
+ driver = SandthornDriverSequel.driver_from_url(url: url)
68
+ Sandthorn.event_stores.add(:other, driver)
69
+ migrator = SandthornDriverSequel::Migration.new url: url
70
+ SandthornDriverSequel.migrate_db url: url
71
+ migrator.send(:clear_for_test)
72
+ end
15
73
  end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ class InitChange
4
+ include Sandthorn::AggregateRoot
5
+ attr_reader :foo
6
+ def initialize foo: nil
7
+ @foo = foo
8
+ end
9
+ end
10
+ def change_init
11
+ InitChange.class_eval do
12
+ define_method :initialize, lambda { @foo = :foo }
13
+ end
14
+ end
15
+ describe "when the initialize-method changes" do
16
+ it "should be possible to replay anyway" do
17
+ aggregate = InitChange.new foo: :bar
18
+ events = aggregate.aggregate_events
19
+ change_init
20
+ with_change = InitChange.new
21
+ expect(with_change.foo).to eql :foo
22
+ replayed = InitChange.aggregate_build(events)
23
+ expect(replayed.foo).to eql :bar
24
+ end
25
+ end
@@ -2,14 +2,16 @@ require 'spec_helper'
2
2
 
3
3
  class AnAggregate
4
4
  include Sandthorn::AggregateRoot
5
- attr_accessor :test_block_count
6
- def initialize
7
- @test_block_count = false
8
- end
9
5
  def touch; touched; end
10
6
  def touched; commit; end
11
7
  end
12
8
 
9
+ module Outer
10
+ module Inner
11
+ class OtherAggregate < AnAggregate; end
12
+ end
13
+ end
14
+
13
15
  describe Sandthorn do
14
16
  before(:each) {
15
17
  @aggregate = AnAggregate.new
@@ -17,24 +19,37 @@ describe Sandthorn do
17
19
  @aggregate.save
18
20
  }
19
21
 
20
- context "when doing snapshots" do
22
+ describe "::obsolete_snapshot" do
21
23
  it "retrieves a list of obsolete snapshots" do
22
24
  obsolete_aggregates = Sandthorn.obsolete_snapshots type_names: [AnAggregate], min_event_distance: 0
23
25
  expect(obsolete_aggregates).to_not be_empty
24
26
  end
25
27
 
26
28
  it "accepts a block that is applied to each aggregate" do
27
- obsolete_aggregates = []
28
- Sandthorn.obsolete_snapshots type_names: [AnAggregate], min_event_distance: 0 do |aggr|
29
- aggr.test_block_count = true
30
- obsolete_aggregates << aggr
31
- end
32
- expect(obsolete_aggregates.all? { |aggregate| aggregate.test_block_count == true }).to be_truthy
29
+ obsolete_aggregates = Sandthorn.obsolete_snapshots type_names: [AnAggregate], min_event_distance: 0
30
+ expect do |block|
31
+ Sandthorn.obsolete_snapshots type_names: [AnAggregate], min_event_distance: 0, &block
32
+ end.to yield_successive_args(*obsolete_aggregates)
33
33
  end
34
34
 
35
35
  it "only retrieves aggregates older than min_event_distance" do
36
36
  obsolete_aggregates = Sandthorn.obsolete_snapshots type_names: [AnAggregate], min_event_distance: 10
37
37
  expect(obsolete_aggregates).to be_empty
38
38
  end
39
+
40
+ context "when the aggregate has been declared in a module" do
41
+
42
+ before do
43
+ Outer::Inner::OtherAggregate.new.tap do |agg|
44
+ agg.touch
45
+ agg.save
46
+ end
47
+ end
48
+
49
+ it "doesn't crash" do
50
+ obsolete_aggregates = Sandthorn.obsolete_snapshots type_names: [Outer::Inner::OtherAggregate], min_event_distance: 0
51
+ expect(obsolete_aggregates).to all(be_a_kind_of(Outer::Inner::OtherAggregate))
52
+ end
53
+ end
39
54
  end
40
55
  end
data/spec/spec_helper.rb CHANGED
@@ -5,12 +5,13 @@
5
5
  #
6
6
  # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
7
  require 'coveralls'
8
+ Coveralls.wear!
8
9
  require "ap"
9
10
  require "bundler"
10
11
  require "sandthorn_driver_sequel"
12
+ require "support/custom_matchers"
11
13
 
12
14
  Bundler.require
13
- Coveralls.wear!
14
15
 
15
16
  module Helpers
16
17
  def class_including(mod)
@@ -36,8 +37,10 @@ def spec_db
36
37
  end
37
38
  def sqlite_store_setup
38
39
  url = spec_db
39
- catch_all_config = [ { driver: SandthornDriverSequel.driver_from_url(url: url) } ]
40
- Sandthorn.configuration = catch_all_config
40
+ driver = SandthornDriverSequel.driver_from_url(url: url)
41
+ Sandthorn.configure do |c|
42
+ c.event_store = driver
43
+ end
41
44
  migrator = SandthornDriverSequel::Migration.new url: url
42
45
  SandthornDriverSequel.migrate_db url: url
43
46
  migrator.send(:clear_for_test)
@@ -0,0 +1,7 @@
1
+ require 'rspec/expectations'
2
+
3
+ RSpec::Matchers.define :have_aggregate_type do |expected|
4
+ match do |actual|
5
+ actual[:aggregate_type].to_s == expected.to_s
6
+ end
7
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sandthorn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lars Krantz
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-10-18 00:00:00.000000000 Z
12
+ date: 2015-03-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -43,16 +43,16 @@ dependencies:
43
43
  name: rspec
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - ">="
46
+ - - "~>"
47
47
  - !ruby/object:Gem::Version
48
- version: '0'
48
+ version: '3.0'
49
49
  type: :development
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
- - - ">="
53
+ - - "~>"
54
54
  - !ruby/object:Gem::Version
55
- version: '0'
55
+ version: '3.0'
56
56
  - !ruby/object:Gem::Dependency
57
57
  name: gem-release
58
58
  requirement: !ruby/object:Gem::Requirement
@@ -193,6 +193,7 @@ files:
193
193
  - lib/sandthorn/aggregate_root_snapshot.rb
194
194
  - lib/sandthorn/errors.rb
195
195
  - lib/sandthorn/event_inspector.rb
196
+ - lib/sandthorn/event_stores.rb
196
197
  - lib/sandthorn/version.rb
197
198
  - sandthorn.gemspec
198
199
  - spec/aggregate_delta_spec.rb
@@ -203,9 +204,12 @@ files:
203
204
  - spec/db/sequel_driver.sqlite3_old
204
205
  - spec/different_driver_spec.rb
205
206
  - spec/event_inspector_spec.rb
207
+ - spec/event_stores_spec.rb
206
208
  - spec/get_events_spec.rb
209
+ - spec/initialize_signature_change_spec.rb
207
210
  - spec/sandthorn_spec.rb
208
211
  - spec/spec_helper.rb
212
+ - spec/support/custom_matchers.rb
209
213
  - spec/tracing_spec.rb
210
214
  homepage: ''
211
215
  licenses:
@@ -227,7 +231,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
227
231
  version: '0'
228
232
  requirements: []
229
233
  rubyforge_project:
230
- rubygems_version: 2.2.2
234
+ rubygems_version: 2.4.3
231
235
  signing_key:
232
236
  specification_version: 4
233
237
  summary: Event sourcing gem
@@ -240,8 +244,11 @@ test_files:
240
244
  - spec/db/sequel_driver.sqlite3_old
241
245
  - spec/different_driver_spec.rb
242
246
  - spec/event_inspector_spec.rb
247
+ - spec/event_stores_spec.rb
243
248
  - spec/get_events_spec.rb
249
+ - spec/initialize_signature_change_spec.rb
244
250
  - spec/sandthorn_spec.rb
245
251
  - spec/spec_helper.rb
252
+ - spec/support/custom_matchers.rb
246
253
  - spec/tracing_spec.rb
247
254
  has_rdoc: