sequent 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/sequent/core/command.rb +0 -3
- data/lib/sequent/core/command_record.rb +15 -8
- data/lib/sequent/core/core.rb +1 -0
- data/lib/sequent/core/event.rb +12 -6
- data/lib/sequent/core/event_record.rb +19 -12
- data/lib/sequent/core/event_store.rb +3 -3
- data/lib/sequent/core/helpers/association_validator.rb +2 -2
- data/lib/sequent/core/helpers/attribute_support.rb +10 -2
- data/lib/sequent/core/helpers/param_support.rb +1 -1
- data/lib/sequent/core/helpers/type_conversion_support.rb +1 -1
- data/lib/sequent/core/sequent_oj.rb +20 -0
- data/lib/sequent/core/value_object.rb +0 -4
- data/lib/sequent/test/command_handler_helpers.rb +3 -3
- data/lib/version.rb +1 -1
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 06ef0bc6b614da70a42d8318cd2c4e135f263dc9
|
4
|
+
data.tar.gz: 00e06d5d6126eaef0a31a191b36872553be04e19
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d399fbc756aabc8ea5e8a81629c59b5fbe322c36e6597f8bd30112941dfd1185e7621b6ea9b90d8fef64756fb05f0f06c03b9b383ec89ec727a0ef5eaa20fec6
|
7
|
+
data.tar.gz: c4820f86874017e0f8c44e634d81de5bdf7c5e0f983bdba5173502104180c7351a9d4e8ee567ac79261b7451c4ad4e5003f21b0f0f5a22ef38c30480401f0c64
|
data/lib/sequent/core/command.rb
CHANGED
@@ -10,7 +10,6 @@ module Sequent
|
|
10
10
|
# Base command
|
11
11
|
class BaseCommand
|
12
12
|
include ActiveModel::Validations,
|
13
|
-
ActiveModel::Serializers::JSON,
|
14
13
|
Sequent::Core::Helpers::Copyable,
|
15
14
|
Sequent::Core::Helpers::AttributeSupport,
|
16
15
|
Sequent::Core::Helpers::UuidHelper,
|
@@ -21,8 +20,6 @@ module Sequent
|
|
21
20
|
|
22
21
|
attrs created_at: DateTime
|
23
22
|
|
24
|
-
self.include_root_in_json = false
|
25
|
-
|
26
23
|
def initialize(args = {})
|
27
24
|
update_all_attributes args
|
28
25
|
@created_at = DateTime.now
|
@@ -1,15 +1,12 @@
|
|
1
1
|
require 'active_record'
|
2
|
+
require_relative 'sequent_oj'
|
3
|
+
|
2
4
|
module Sequent
|
3
5
|
module Core
|
4
|
-
# For storing Sequent::Core::Command in the database using active_record
|
5
|
-
class CommandRecord < ActiveRecord::Base
|
6
|
-
|
7
|
-
self.table_name = "command_records"
|
8
|
-
|
9
|
-
validates_presence_of :command_type, :command_json
|
10
6
|
|
7
|
+
module SerializesCommand
|
11
8
|
def command
|
12
|
-
args =
|
9
|
+
args = Sequent::Core::Oj.strict_load(command_json)
|
13
10
|
Class.const_get(command_type.to_sym).deserialize_from_json(args)
|
14
11
|
end
|
15
12
|
|
@@ -19,8 +16,18 @@ module Sequent
|
|
19
16
|
self.organization_id = command.organization_id if command.respond_to? :organization_id
|
20
17
|
self.user_id = command.user_id if command.respond_to? :user_id
|
21
18
|
self.command_type = command.class.name
|
22
|
-
self.command_json = command.
|
19
|
+
self.command_json = Sequent::Core::Oj.dump(command.attributes)
|
23
20
|
end
|
24
21
|
end
|
22
|
+
|
23
|
+
# For storing Sequent::Core::Command in the database using active_record
|
24
|
+
class CommandRecord < ActiveRecord::Base
|
25
|
+
include SerializesCommand
|
26
|
+
|
27
|
+
self.table_name = "command_records"
|
28
|
+
|
29
|
+
validates_presence_of :command_type, :command_json
|
30
|
+
|
31
|
+
end
|
25
32
|
end
|
26
33
|
end
|
data/lib/sequent/core/core.rb
CHANGED
data/lib/sequent/core/event.rb
CHANGED
@@ -10,10 +10,8 @@ module Sequent
|
|
10
10
|
include Sequent::Core::Helpers::StringSupport,
|
11
11
|
Sequent::Core::Helpers::EqualSupport,
|
12
12
|
Sequent::Core::Helpers::AttributeSupport,
|
13
|
-
Sequent::Core::Helpers::Copyable
|
14
|
-
ActiveModel::Serializers::JSON
|
13
|
+
Sequent::Core::Helpers::Copyable
|
15
14
|
attrs aggregate_id: String, sequence_number: Integer, created_at: DateTime
|
16
|
-
self.include_root_in_json = false
|
17
15
|
|
18
16
|
def initialize(args = {})
|
19
17
|
update_all_attributes args
|
@@ -24,14 +22,22 @@ module Sequent
|
|
24
22
|
|
25
23
|
def payload
|
26
24
|
result = {}
|
27
|
-
instance_variables
|
25
|
+
instance_variables
|
26
|
+
.reject { |k| payload_variables.include?(k) }
|
27
|
+
.select { |k| self.class.types.keys.include?(to_attribute_name(k))}
|
28
|
+
.each do |k|
|
28
29
|
result[k.to_s[1 .. -1].to_sym] = instance_variable_get(k)
|
29
30
|
end
|
30
31
|
result
|
31
32
|
end
|
32
33
|
protected
|
33
34
|
def payload_variables
|
34
|
-
%
|
35
|
+
%i{@aggregate_id @sequence_number @created_at}
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
def to_attribute_name(instance_variable_name)
|
40
|
+
instance_variable_name[1 .. -1].to_sym
|
35
41
|
end
|
36
42
|
|
37
43
|
end
|
@@ -47,7 +53,7 @@ module Sequent
|
|
47
53
|
|
48
54
|
protected
|
49
55
|
def payload_variables
|
50
|
-
super << "@organization_id"
|
56
|
+
super << :"@organization_id"
|
51
57
|
end
|
52
58
|
|
53
59
|
end
|
@@ -1,21 +1,14 @@
|
|
1
|
-
require 'oj'
|
2
1
|
require 'active_record'
|
2
|
+
require_relative 'sequent_oj'
|
3
3
|
|
4
4
|
module Sequent
|
5
5
|
module Core
|
6
|
-
class EventRecord < ActiveRecord::Base
|
7
|
-
|
8
|
-
self.table_name = "event_records"
|
9
|
-
|
10
|
-
belongs_to :command_record
|
11
|
-
|
12
|
-
validates_presence_of :aggregate_id, :sequence_number, :event_type, :event_json
|
13
|
-
validates_numericality_of :sequence_number
|
14
6
|
|
7
|
+
module SerializesEvent
|
15
8
|
|
16
9
|
def event
|
17
|
-
payload = Oj.strict_load(event_json)
|
18
|
-
Class.const_get(event_type.to_sym).deserialize_from_json(payload)
|
10
|
+
payload = Sequent::Core::Oj.strict_load(self.event_json)
|
11
|
+
Class.const_get(self.event_type.to_sym).deserialize_from_json(payload)
|
19
12
|
end
|
20
13
|
|
21
14
|
def event=(event)
|
@@ -24,11 +17,25 @@ module Sequent
|
|
24
17
|
self.organization_id = event.organization_id if event.respond_to?(:organization_id)
|
25
18
|
self.event_type = event.class.name
|
26
19
|
self.created_at = event.created_at
|
27
|
-
self.event_json = event.
|
20
|
+
self.event_json = Sequent::Core::Oj.dump(event.attributes)
|
28
21
|
end
|
29
22
|
|
30
23
|
end
|
31
24
|
|
25
|
+
class EventRecord < ActiveRecord::Base
|
26
|
+
include SerializesEvent
|
27
|
+
|
28
|
+
self.table_name = "event_records"
|
29
|
+
|
30
|
+
belongs_to :command_record
|
31
|
+
|
32
|
+
validates_presence_of :aggregate_id, :sequence_number, :event_type, :event_json
|
33
|
+
validates_numericality_of :sequence_number
|
34
|
+
|
35
|
+
|
36
|
+
|
37
|
+
end
|
38
|
+
|
32
39
|
end
|
33
40
|
end
|
34
41
|
|
@@ -1,5 +1,5 @@
|
|
1
|
-
require 'oj'
|
2
1
|
require_relative 'event_record'
|
2
|
+
require_relative 'sequent_oj'
|
3
3
|
|
4
4
|
module Sequent
|
5
5
|
module Core
|
@@ -50,7 +50,7 @@ module Sequent
|
|
50
50
|
event_types = {}
|
51
51
|
@record_class.connection.select_all("select event_type, event_json from #{@record_class.table_name} where aggregate_id = '#{aggregate_id}' order by sequence_number asc").map! do |event_hash|
|
52
52
|
event_type = event_hash["event_type"]
|
53
|
-
event_json = Oj.strict_load(event_hash["event_json"])
|
53
|
+
event_json = Sequent::Core::Oj.strict_load(event_hash["event_json"])
|
54
54
|
unless event_types.has_key?(event_type)
|
55
55
|
event_types[event_type] = Class.const_get(event_type.to_sym)
|
56
56
|
end
|
@@ -67,7 +67,7 @@ module Sequent
|
|
67
67
|
event_types = {}
|
68
68
|
event_stream.each do |event_hash|
|
69
69
|
event_type = event_hash["event_type"]
|
70
|
-
payload = Oj.strict_load(event_hash["event_json"])
|
70
|
+
payload = Sequent::Core::Oj.strict_load(event_hash["event_json"])
|
71
71
|
unless event_types.has_key?(event_type)
|
72
72
|
event_types[event_type] = Class.const_get(event_type.to_sym)
|
73
73
|
end
|
@@ -24,7 +24,7 @@ module Sequent
|
|
24
24
|
next unless association # since ruby 2.0...?
|
25
25
|
value = record.instance_variable_get("@#{association.to_s}")
|
26
26
|
if value && incorrect_type?(value, record, association)
|
27
|
-
record.errors[association] = "is not of type #{record.
|
27
|
+
record.errors[association] = "is not of type #{record.class.types[association]}"
|
28
28
|
elsif value && value.kind_of?(Array)
|
29
29
|
item_type = record.class.type_for(association).item_type
|
30
30
|
record.errors[association] = "is invalid" if all_valid?(value, item_type)
|
@@ -37,7 +37,7 @@ module Sequent
|
|
37
37
|
private
|
38
38
|
|
39
39
|
def incorrect_type?(value, record, association)
|
40
|
-
!value.kind_of?(Array) && record.respond_to?(:
|
40
|
+
!value.kind_of?(Array) && record.class.respond_to?(:types) && !value.kind_of?(record.class.types[association])
|
41
41
|
end
|
42
42
|
|
43
43
|
def all_valid?(value, item_type)
|
@@ -109,9 +109,17 @@ EOS
|
|
109
109
|
end
|
110
110
|
|
111
111
|
|
112
|
-
# needed for active module JSON serialization
|
113
112
|
def attributes
|
114
|
-
|
113
|
+
hash = HashWithIndifferentAccess.new
|
114
|
+
self.class.types.each do |name, _|
|
115
|
+
value = self.instance_variable_get("@#{name}")
|
116
|
+
hash[name] = if value.respond_to?(:attributes)
|
117
|
+
value.attributes
|
118
|
+
else
|
119
|
+
value
|
120
|
+
end
|
121
|
+
end
|
122
|
+
hash
|
115
123
|
end
|
116
124
|
|
117
125
|
def validation_errors(prefix = nil)
|
@@ -14,7 +14,7 @@ module Sequent
|
|
14
14
|
def from_params(params = {})
|
15
15
|
result = allocate
|
16
16
|
params = HashWithIndifferentAccess.new(params)
|
17
|
-
result.
|
17
|
+
result.class.types.each do |attribute, type|
|
18
18
|
value = params[attribute]
|
19
19
|
|
20
20
|
next if value.blank?
|
@@ -10,7 +10,7 @@ module Sequent
|
|
10
10
|
module TypeConversionSupport
|
11
11
|
def parse_attrs_to_correct_types
|
12
12
|
the_copy = dup
|
13
|
-
the_copy.
|
13
|
+
the_copy.class.types.each do |name, type|
|
14
14
|
raw_value = the_copy.send("#{name}")
|
15
15
|
next if raw_value.nil?
|
16
16
|
if raw_value.respond_to?(:parse_attrs_to_correct_types)
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'oj'
|
2
|
+
|
3
|
+
module Sequent
|
4
|
+
module Core
|
5
|
+
# small wrapper class to centralize oj and its settings.
|
6
|
+
class Oj
|
7
|
+
|
8
|
+
::Oj.default_options={mode: :compat}
|
9
|
+
|
10
|
+
def self.strict_load(json)
|
11
|
+
::Oj.strict_load(json, {})
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.dump(obj)
|
15
|
+
::Oj.dump(obj)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -31,14 +31,10 @@ module Sequent
|
|
31
31
|
Sequent::Core::Helpers::Copyable,
|
32
32
|
Sequent::Core::Helpers::AttributeSupport,
|
33
33
|
Sequent::Core::Helpers::ParamSupport,
|
34
|
-
ActiveModel::Serializers::JSON,
|
35
34
|
ActiveModel::Validations
|
36
35
|
include Sequent::Core::Helpers::TypeConversionSupport
|
37
36
|
|
38
|
-
self.include_root_in_json=false
|
39
|
-
|
40
37
|
def initialize(args = {})
|
41
|
-
@errors = ActiveModel::Errors.new(self)
|
42
38
|
update_all_attributes args
|
43
39
|
end
|
44
40
|
|
@@ -61,12 +61,12 @@ module Sequent
|
|
61
61
|
|
62
62
|
private
|
63
63
|
def serialize_events(events)
|
64
|
-
events.map { |event| [event.class.name.to_sym, event
|
64
|
+
events.map { |event| [event.class.name.to_sym, Sequent::Core::Oj.dump(event)] }
|
65
65
|
end
|
66
66
|
|
67
67
|
def deserialize_events(events)
|
68
68
|
events.map do |type, json|
|
69
|
-
Class.const_get(type).deserialize_from_json(
|
69
|
+
Class.const_get(type).deserialize_from_json(Sequent::Core::Oj.strict_load(json))
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
@@ -87,7 +87,7 @@ module Sequent
|
|
87
87
|
def then_events *events
|
88
88
|
@event_store.stored_events.map(&:class).should == events.map(&:class)
|
89
89
|
@event_store.stored_events.zip(events).each do |actual, expected|
|
90
|
-
|
90
|
+
Sequent::Core::Oj.strict_load(Sequent::Core::Oj.dump(actual.payload)).should == Sequent::Core::Oj.strict_load(Sequent::Core::Oj.dump(expected.payload)) if expected
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
data/lib/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sequent
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lars Vonk
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2015-04-24 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
@@ -110,6 +110,20 @@ dependencies:
|
|
110
110
|
- - "~>"
|
111
111
|
- !ruby/object:Gem::Version
|
112
112
|
version: '1.1'
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: rake
|
115
|
+
requirement: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - "~>"
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '10.4'
|
120
|
+
type: :development
|
121
|
+
prerelease: false
|
122
|
+
version_requirements: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - "~>"
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '10.4'
|
113
127
|
description: Sequent is a CQRS and event sourcing framework for Ruby.
|
114
128
|
email:
|
115
129
|
- lars.vonk@gmail.com
|
@@ -152,6 +166,7 @@ files:
|
|
152
166
|
- lib/sequent/core/record_sessions/active_record_session.rb
|
153
167
|
- lib/sequent/core/record_sessions/record_sessions.rb
|
154
168
|
- lib/sequent/core/record_sessions/replay_events_session.rb
|
169
|
+
- lib/sequent/core/sequent_oj.rb
|
155
170
|
- lib/sequent/core/tenant_event_store.rb
|
156
171
|
- lib/sequent/core/transactions/active_record_transaction_provider.rb
|
157
172
|
- lib/sequent/core/transactions/no_transactions.rb
|
@@ -188,4 +203,3 @@ signing_key:
|
|
188
203
|
specification_version: 4
|
189
204
|
summary: Event sourcing framework for Ruby
|
190
205
|
test_files: []
|
191
|
-
has_rdoc:
|