aggregate_root 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7b7092c2b7985985ffa355189839d94ef36599f3
4
+ data.tar.gz: e421f24047e7491d6a0fc052d020224102ff7f16
5
+ SHA512:
6
+ metadata.gz: 23493dde4e5a29af698b702d8c8f5cda809113ad1f7fa435dc8c508196e6c74d55eb41fb63a031431955944c615aa51498f1e9bb169849bad29cf9d04aee52e9
7
+ data.tar.gz: 7cee5df16ff7570043cd1a6f54d668abb27791a28718b9fd407f0c008d4040dfb6042e5fcf2bad815ca5cfd6d2120c02b1f00bc7c982c9192d03d3e2e6dfe35f
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ### HEAD
2
+
3
+ ### 0.0.1 (28.01.2016)
4
+
5
+ Initial release. Code extracted from RailsEventStore.
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
3
+ gem 'codeclimate-test-reporter', group: :test, require: nil
data/LICENSE ADDED
@@ -0,0 +1,5 @@
1
+ Copyright (c) Arkency
2
+
3
+ Rails EventStore is an Open Source project licensed under the terms of
4
+ the LGPLv3 license. Please see <http://www.gnu.org/licenses/lgpl-3.0.html>
5
+ for license text.
data/README.md ADDED
@@ -0,0 +1,111 @@
1
+ # AggregateRoot
2
+
3
+ Event sourced (with Rails Event Store) aggregate root implementation.
4
+
5
+ ## Installation
6
+
7
+ * Add following line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'aggregate_root'
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ To create a new aggregate domain object include `AggregateRoot::Base` module.
16
+ It is important to assign `id` at initializer - it will be used as a event store stream name.
17
+
18
+ ```ruby
19
+ class Order
20
+ include AggregateRoot::Base
21
+
22
+ def initialize(id = generate_id)
23
+ self.id = id
24
+ # any other code here
25
+ end
26
+
27
+ # ... more later
28
+ end
29
+ ```
30
+
31
+ #### Define aggregate logic
32
+
33
+ ```ruby
34
+ OrderSubmitted = Class.new(RailsEventStore::Event)
35
+ OrderExpired = Class.new(RailsEventStore::Event)
36
+ ```
37
+
38
+ ```ruby
39
+ class Order
40
+ include AggregateRoot::Base
41
+ HasBeenAlreadySubmitted = Class.new(StandardError)
42
+ HasExpired = Class.new(StandardError)
43
+
44
+ def initialize(id = generate_id)
45
+ self.id = id
46
+ self.state = :new
47
+ # any other code here
48
+ end
49
+
50
+ def submit
51
+ raise HasBeenAlreadySubmitted if state == :submitted
52
+ raise HasExpired if state == :expired
53
+ apply OrderSubmitted.new(delivery_date: Time.now + 24.hours)
54
+ end
55
+
56
+ def expire
57
+ apply OrderExpired.new
58
+ end
59
+
60
+ private
61
+ attr_accessor :state
62
+
63
+ def apply_order_submitted(event)
64
+ self.state = :submitted
65
+ end
66
+
67
+ def apply_order_expired(event)
68
+ self.state = :expired
69
+ end
70
+ end
71
+ ```
72
+
73
+ #### Loading an aggregate root object from event store
74
+
75
+ ```ruby
76
+ repository = ArggregateRoot::Repository.new
77
+ order = Order.new(ORDER_ID)
78
+ repository.load(order)
79
+ ```
80
+
81
+ Load gets all domain event stored for the aggregate in event store and apply them
82
+ in order to given aggregate to rebuild aggregate's state.
83
+
84
+ #### Storing an aggregate root's changes in event store
85
+
86
+ ```ruby
87
+ repository = ArggregateRoot::Repository.new
88
+ order = Order.new(ORDER_ID)
89
+ repository.load(order)
90
+ order.submit
91
+ repository.store(order)
92
+ ```
93
+
94
+ Store gets all unpublished aggregate's domain events (created by executing a domain logic method like `submit`)
95
+ and publish them in order of creation to event store.
96
+
97
+ #### Resources
98
+
99
+ There're already few blogposts about Rails EventStore. Check them out:
100
+
101
+ * [Why use Event Sourcing](http://blog.arkency.com/2015/03/why-use-event-sourcing/)
102
+ * [The Event Store for Rails developers](http://blog.arkency.com/2015/04/the-event-store-for-rails-developers/)
103
+ * [Fast introduction to Event Sourcing for Ruby programmers](http://blog.arkency.com/2015/03/fast-introduction-to-event-sourcing-for-ruby-programmers/)
104
+
105
+ ## About
106
+
107
+ <img src="http://arkency.com/images/arkency.png" alt="Arkency" width="20%" align="left" />
108
+
109
+ Rails Event Store is funded and maintained by Arkency. Check out our other [open-source projects](https://github.com/arkency).
110
+
111
+ You can also [hire us](http://arkency.com) or [read our blog](http://blog.arkency.com).
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+ RSpec::Core::RakeTask.new(:spec)
4
+ task default: :spec
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'aggregate_root/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'aggregate_root'
8
+ spec.version = AggregateRoot::VERSION
9
+ spec.authors = ['mpraglowski']
10
+ spec.email = ['m@praglowski.com']
11
+
12
+ spec.summary = %q{Event sourced (with Rails Event Store) aggregate root implementation}
13
+ spec.description = %q{Event sourced (with Rails Event Store) aggregate root implementation}
14
+ spec.homepage = ''
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = 'exe'
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_development_dependency 'bundler', '~> 1.9'
22
+ spec.add_development_dependency 'rake', '~> 10.0'
23
+ spec.add_development_dependency 'pry'
24
+ spec.add_development_dependency 'rspec'
25
+ spec.add_development_dependency 'rails', '~> 4.2.1'
26
+
27
+ spec.add_dependency 'rails_event_store', '>= 0.1.4'
28
+ spec.add_dependency 'activesupport', '>= 3.0'
29
+ end
@@ -0,0 +1,5 @@
1
+ require 'rails_event_store'
2
+
3
+ require 'aggregate_root/version'
4
+ require 'aggregate_root/repository'
5
+ require 'aggregate_root/base'
@@ -0,0 +1,31 @@
1
+ require 'active_support/inflector'
2
+
3
+ module AggregateRoot
4
+ module Base
5
+ attr_reader :id
6
+
7
+ def apply(event)
8
+ apply_event(event)
9
+ unpublished_events << event
10
+ end
11
+
12
+ def apply_old_event(event)
13
+ apply_event(event)
14
+ end
15
+
16
+ def unpublished_events
17
+ @unpublished_events ||= []
18
+ end
19
+
20
+ private
21
+ attr_writer :id
22
+
23
+ def apply_event(event)
24
+ send("apply_#{event.event_type.underscore.gsub('/', '_')}", event)
25
+ end
26
+
27
+ def generate_uuid
28
+ SecureRandom.uuid
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,26 @@
1
+ module AggregateRoot
2
+ class Repository
3
+ def initialize(event_store = default_event_store)
4
+ @event_store = event_store
5
+ end
6
+
7
+ def store(aggregate)
8
+ aggregate.unpublished_events.each do |event|
9
+ event_store.publish_event(event, aggregate.id)
10
+ end
11
+ end
12
+
13
+ def load(aggregate)
14
+ events = event_store.read_all_events(aggregate.id)
15
+ events.each do |event|
16
+ aggregate.apply_old_event(event)
17
+ end
18
+ end
19
+
20
+ attr_accessor :event_store
21
+
22
+ def default_event_store
23
+ RailsEventStore::Client.new
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,3 @@
1
+ module AggregateRoot
2
+ VERSION = '0.0.1'
3
+ end
metadata ADDED
@@ -0,0 +1,152 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: aggregate_root
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - mpraglowski
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-01-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.9'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.9'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rails
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 4.2.1
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 4.2.1
83
+ - !ruby/object:Gem::Dependency
84
+ name: rails_event_store
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: 0.1.4
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: 0.1.4
97
+ - !ruby/object:Gem::Dependency
98
+ name: activesupport
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '3.0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '3.0'
111
+ description: Event sourced (with Rails Event Store) aggregate root implementation
112
+ email:
113
+ - m@praglowski.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".gitignore"
119
+ - CHANGELOG.md
120
+ - Gemfile
121
+ - LICENSE
122
+ - README.md
123
+ - Rakefile
124
+ - aggregate_root.gemspec
125
+ - lib/aggregate_root.rb
126
+ - lib/aggregate_root/base.rb
127
+ - lib/aggregate_root/repository.rb
128
+ - lib/aggregate_root/version.rb
129
+ homepage: ''
130
+ licenses: []
131
+ metadata: {}
132
+ post_install_message:
133
+ rdoc_options: []
134
+ require_paths:
135
+ - lib
136
+ required_ruby_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ required_rubygems_version: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ requirements: []
147
+ rubyforge_project:
148
+ rubygems_version: 2.2.5
149
+ signing_key:
150
+ specification_version: 4
151
+ summary: Event sourced (with Rails Event Store) aggregate root implementation
152
+ test_files: []