aggregate_root 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []