jouba 1.0.1 → 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
2
  SHA1:
3
- metadata.gz: a950ed83af66e155fdc222f59f7d19fc75b794bc
4
- data.tar.gz: 9f1c29d98bb2629d203fa1d488835dba5e7fe596
3
+ metadata.gz: 9e6660abb8c21ca75fd3e50326ac42be55042e44
4
+ data.tar.gz: 8275f30c736cc526a067dd62133c9793b9d54a70
5
5
  SHA512:
6
- metadata.gz: 2ea2281b2b8e62388b3c881de115e43b9e88db12e92e2005098edc8b0a27517d27a8f5558a5d80e2eb78014558707e29b7adad18b2235f7a9951ff48bbef844b
7
- data.tar.gz: 748a5ef33c0af9a63d5b306988b2117cb25e6b9bfea4d7a80a651a551240cd99849013b314c905db85b4cee5068991484428b42133c88dacf2b4ef8bab05b8f5
6
+ metadata.gz: 3db76134f73e65253c60d0ffce827641d50b7039e8f0d42481a25cc572229cd903619485efe1e93acd4d9a91d2998cb858c47b64e245e7191c2ce9b8f7da4c2c
7
+ data.tar.gz: cd2a7c8db64aececdf803d9c55ebd9df5cdafaaea0fdd12b03c913746d46e9f026988c7f66c2cd1c5d9044788fa67710443fa755aff8b552760544c7d1ca15cb
data/Gemfile CHANGED
@@ -1,7 +1,7 @@
1
1
  source "http://rubygems.org"
2
2
 
3
3
  gem 'hashie', '~> 3.4'
4
- gem 'wisper', '~>1.6'
4
+ gem 'wisper', '~>2.0.0.rc1'
5
5
  gem 'locality-uuid'
6
6
 
7
7
  group :development do
@@ -88,7 +88,7 @@ GEM
88
88
  slop (3.5.0)
89
89
  systemu (2.6.4)
90
90
  thread_safe (0.3.4)
91
- wisper (1.6.0)
91
+ wisper (2.0.0.rc1)
92
92
 
93
93
  PLATFORMS
94
94
  ruby
@@ -103,4 +103,4 @@ DEPENDENCIES
103
103
  rspec (~> 2.14)
104
104
  rubocop (~> 0.23)
105
105
  simplecov (~> 0)
106
- wisper (~> 1.6)
106
+ wisper (~> 2.0.0.rc1)
data/README.md CHANGED
@@ -1,70 +1,69 @@
1
- # jouba
1
+ # Jouba
2
2
 
3
+ [![Join the chat at https://gitter.im/gregory/jouba](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/gregory/jouba?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
3
4
 
4
- ```ruby
5
- class Customer < Hashie::Dash
6
- include Jouba::Aggregate.new(prefix: :on)
7
- property :uuid
8
- property :name
5
+ ![](https://dl.dropboxusercontent.com/u/19927862/jouba.png)
9
6
 
10
- def self.create(attributes)
11
- Customer.new(uuid: SecureRandom.uuid).tap do |customer|
12
- customer.create(attributes.merge(uuid: customer.uuid))
13
- end
14
- end
15
7
 
16
- def create(attributes)
17
- emit(:created, attributes)
18
- end
8
+ ## WTF?
19
9
 
20
- private
10
+ Jouba aims to be a minimalist framework in pure ruby for [event sourcing](http://martinfowler.com/eaaDev/EventSourcing.html), [CQRS](http://martinfowler.com/bliki/CQRS.html) ready.
21
11
 
22
- def on_created(attributes)
23
- update_attributes!(attributes)
24
- end
25
- end
12
+ **TL; DR**:
26
13
 
27
- class Admin
28
- include Jouba::Aggregate.new(prefix: :on) # include Wisper and Anima
14
+ **Event sourcing**:
15
+ > The fundamental idea of Event Sourcing is that of ensuring every change to the state of an application is captured in an event object, and that these event objects are themselves stored in the sequence they were applied for the same lifetime as the application state itself.
29
16
 
30
- def self.create(attributes)
31
- Admin.new(uuid: SecureRandom.uuid).tap do |admin|
32
- admin.create(attributes.merge(uuid: customer.uuid))
33
- end
34
- end
35
17
 
36
- def create(attributes)
37
- emit(:created, attributes)
38
- end
18
+ **CQRS**:
19
+ > It's a pattern that I first heard described by Greg Young. At its heart is a simple notion that you can use a different model to update information than the model you use to read information.
39
20
 
40
- private
21
+ ## FAQ:
41
22
 
42
- def on_created(attributes)
43
- update_attributes!(attributes)
44
- end
45
- end
23
+ * Is it in production yet?
24
+ * Not that i know of. In my case, not yet since i've been pretty busy with other stuffs and this was initially part of a side project, but i should be pretty reactive for PR/issues so feel free to use/improve it.
25
+
26
+
46
27
 
28
+ ## Pub/Sub
47
29
 
48
- Jouba.emit('us.computer1.cpu', :idle, {value: 50})
49
- Jouba.stream('us.computer1.cpu').since(1.month.ago).where({value: ->(v) { v >= 20 }})
30
+ Jouba ships with a minimalist API to emit events and subscribe listeners (listeners could operate asynchronously) and retrieve events from the store that is set at `Jouba.config.Store` (by default this will be an [in memory store](https://github.com/gregory/jouba/blob/master/lib/jouba/store.rb#L47).
50
31
 
51
- Jouba.config.Cache = Jouba::Cache::Memory.new
52
- require 'jouba/aggregate'
53
- customer_params = { fname: 'foo', lname: 'bar' }
32
+ At it's core, it relies on the excellent [wisper](https://github.com/krisleech/wisper) gem so you have all it's awesomeness for free.
54
33
 
55
- c = Customer.create(customer_params, true)
56
- c.fname # => "foo"
57
- c.uuid # => 123
58
- c.to_key # => "Customer.123"
34
+ ```ruby
59
35
 
60
- d = Customer.find(c.uuid)
36
+ Jouba.emit('us.computer1.cpu', :idle, {value: 50})
37
+ Jouba.subscribe(Logger, on: /.*/, with: :log)
38
+ Jouba.subscribe(Graphite, on: /us.*/, with: :post, async: true).on_error do |error, name,payload|
39
+ #DO SOMETHING
40
+ end
41
+
42
+ Jouba.stream('us.computer1.cpu').since(1.month.ago).where({value: ->(v) { v >= 20 }})
43
+
44
+ class Logger
45
+ def log(params={})
46
+ puts params.map{|k,v| "#{k}=#{v}"}.join(', ')
47
+ end
48
+ end
61
49
 
50
+ class Collector
51
+ def post(params={})
52
+ $statsd.increment params[:key]
53
+ end
54
+ end
62
55
  ```
63
56
 
57
+ ## Event Store (stores all events that has happened)
58
+
59
+ You are free to implement an Event Store as soon as they define `self.stream`and `self.track` methods.
60
+
61
+
64
62
  ```ruby
65
- class Store < AR
66
- set_table_name :events
67
63
 
64
+ class Store < ActiveRecord::Base
65
+ set_table_name :events
66
+
68
67
  scope :since, -> (time) { where('timestamp >= ?', time) }
69
68
 
70
69
  def self.stream(key, params={})
@@ -75,26 +74,179 @@
75
74
  create serialized_event
76
75
  end
77
76
  end
77
+
78
78
 
79
79
  Jouba.config.Store = Store
80
+ Jouba.emit('us.computer1', :disk, {value: 60})
81
+ Jouba.emit('us.computer1', :cpu, {value: 50}) do |event|
82
+ #DO SOME STUFFS
83
+ event.track
84
+ end
85
+ Jouba.stream('us.computer1').where(key: 'us.computer1', name: :cpu).count
86
+
87
+ ```
88
+
89
+ ## Aggregate (handles Commands and generates Events based on the current state)
90
+
91
+ A core concept of CQRS is keeping up to date the state of the data when things changes through commands.
92
+ [Aggregate](http://martinfowler.com/bliki/DDD_Aggregate.html) handles command and generate events based on the current state.
93
+
94
+ Jouba ships with an aggregate module, that provides the host class with an `emit` method in order to emit events to the configured Store (pointed by `Jouba.config.Store`).
95
+ On a distributed system, to avoid eventual consistency on reading data from the db, you should rebuild the state of the aggregate by replaying all the events.
96
+
97
+ After a time, the aggregate could end up with a lot of events, so the trick here is to use what is called a [projection](http://martinfowler.com/eaaDev/EventSourcing.html#ApplicationStateStorage). This has been implemented through a Cach mechanisme, by default [NullCache](https://github.com/gregory/jouba/blob/master/lib/jouba/cache.rb#L5), but you could set it to anything you want.
98
+
99
+ A UUID will be generated for any new aggregate, [even in distributed environment](https://github.com/groupon/locality-uuid.rb)
100
+
101
+ ```ruby
102
+
103
+ require 'jouba/aggregate'
104
+ class Customer < Hashie::Dash
105
+ include Jouba::Aggregate.new(prefix: :on)
106
+
107
+ property :uuid
108
+ property :name
109
+
110
+ def self.create(attributes)
111
+ Customer.new(uuid: SecureRandom.uuid).tap do |customer|
112
+ customer.create(attributes.merge(uuid: customer.uuid))
113
+ end
114
+ end
115
+
116
+ def create(attributes)
117
+ emit(:created, attributes)
118
+ end
119
+
120
+ private
121
+
122
+ def on_created(attributes)
123
+ update_attributes!(attributes)
124
+ end
125
+ end
126
+
127
+ Jouba.config.Cache = Jouba::Cache::Memory.new
128
+ Jouba.subscribe(CustomerAnalytics, on: /Customer.+/, with: :track)
129
+
130
+ c = Customer.create({fname: 'foo', lname: 'bar'})
131
+ c.fname # => "foo"
132
+ c.uuid # => 123
133
+ c.to_key # => "Customer.123"
134
+
135
+ d = Customer.find(c.uuid)
136
+ c == d #=> true
137
+ Customer.stream(c.uuid).count #=> 1
138
+ Customer.stream(c.uuid).first.class #=> Jouba::Event
139
+ Customer.stream(c.uuid).first.uuid # 20be0ffc-314a-bd53-7a50-013a65ca76d2
140
+
141
+ ```
142
+
143
+ Event Sourcing might seem overkill, but this is a little cost comparing to [the advantages](https://lostechies.com/jimmybogard/2011/10/11/event-sourcing-as-a-strategic-advantage/) it will bring to your business
144
+
145
+ ## Event (indicate that something has happened)
146
+
147
+ If you are unhappy with the structure of Jouba::Event, feel free to implement your own!
148
+
149
+ You can access/update to the main parts of jouba from the config
150
+
151
+ ```ruby
152
+ class MyEvent
153
+ # NOTE: the store is accessible from: Jouba.Store or Jouba.config.Store
154
+ def self.serialize(event); end # serialize an event
155
+ def self.deserialize(serialized_event); end # deserialize a serialized event
156
+ def self.stream(key, params={}); end # fetch all the matching events
157
+ def track; end # save to the event store
158
+ end
159
+
160
+ Jouba.config.Event = MyEvent
161
+ ```
162
+
163
+ ## Event Key (generate a key based on the aggregate)
164
+
165
+ If you feels unhappy with the way Jouba::Key is building keys in the aggregate, feel free to implement your own!
166
+
167
+
168
+ ```ruby
169
+
170
+ class MyKey
171
+ attr_reader :class_name, :uuid
172
+
173
+ def initialize(class_name, uuid);
174
+ @class_name, @uuid = class_name, uuid
175
+ end
176
+
177
+ def self.serialize(class_name, uuid); end #return a string of a key
178
+ def self.deserialize(string); end # return a new MyKey
179
+ end
180
+ ```
181
+
182
+ ## Repository
183
+
184
+ Repository is a CQRS concept where you should use repositories to fetch your data for read only. You'll need to keep your repository up to date with all the latest changes.
185
+ The way to achieve this with jouba is by having the repository to subscribe to the aggregates. Repository will ideally translate events into state.
186
+
187
+ ```ruby
188
+ class Admin
189
+ include Jouba::Aggregate.new(prefix: :foo)
190
+
191
+ def self.create(attributes)
192
+ Admin.new(uuid: SecureRandom.uuid).tap do |admin|
193
+ admin.create(attributes.merge(uuid: admin.uuid))
194
+ end
195
+ end
196
+
197
+ def create(attributes)
198
+ emit(:created, attributes)
199
+ end
200
+
201
+ private
202
+
203
+ def foo_created(attributes)
204
+ update_attributes!(attributes)
205
+ end
206
+ end
80
207
 
81
208
  class UserRepository < AR
82
209
  set_table_name :users
83
210
  # must have a key column
84
211
 
85
- def on_created(attributes)
86
- self.create(attributes)
212
+ def self.has_been_created(attributes)
213
+ create(attributes)
87
214
  end
88
- alias :on_created
89
215
  end
90
216
 
91
- Wisper.subscribe(UserRepository.new, scope: :Customer)
217
+ Wisper.subscribe(UserRepository, scope: [:Customer, :Admin], prefix: :has_been) # Note here how 2 aggregates are using the same repository.
218
+ ```
219
+
220
+ ## Cache
221
+
222
+ If you feels unhappy with Jouba::Cache, feel free to implement your own!
223
+
224
+
225
+ ```ruby
226
+
227
+ class MyCache
228
+ def fetch(_)
229
+ yield
230
+ end
231
+
232
+ def refresh(_, _)
233
+ yield
234
+ end
235
+ end
236
+
237
+ Jouba.config.Cache = MyCache.new
92
238
  ```
239
+ ## Why Jouba?
93
240
 
241
+ Jouba is the name of the parrot i grew up with. He never talked but made a hell lot of noise. Going down the path of event sourcing, you'll have a lot of noise first, but then you'll figure out what to do with it.
94
242
 
243
+ ## TODO:
95
244
 
96
- ## Todo
97
- - write a how to in english :)
245
+ * [ ] Better doc (this is a draft :))
246
+ * [ ] Locking Mechanisme
247
+ * [ ] more examples
248
+ * [ ] clean the image
249
+ * [ ] Rename EventStore.get/set into stream/track for better consistency
98
250
 
99
251
  ## Contributing to jouba
100
252
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.1
1
+ 1.1.0
@@ -2,16 +2,14 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: jouba 1.0.1 ruby lib
6
5
 
7
6
  Gem::Specification.new do |s|
8
7
  s.name = "jouba"
9
- s.version = "1.0.1"
8
+ s.version = "1.1.0"
10
9
 
11
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
- s.require_paths = ["lib"]
13
11
  s.authors = ["gregory"]
14
- s.date = "2015-02-03"
12
+ s.date = "2015-04-01"
15
13
  s.description = "Jouba is a tool set for event sourcing: aggregate root, entities and storage"
16
14
  s.email = "greg2502@gmail.com"
17
15
  s.extra_rdoc_files = [
@@ -46,7 +44,8 @@ Gem::Specification.new do |s|
46
44
  ]
47
45
  s.homepage = "http://github.com/gregory/jouba"
48
46
  s.licenses = ["MIT"]
49
- s.rubygems_version = "2.2.2"
47
+ s.require_paths = ["lib"]
48
+ s.rubygems_version = "2.0.14"
50
49
  s.summary = "Jouba is a tool set for event sourcing: aggregate root, entities and storage"
51
50
 
52
51
  if s.respond_to? :specification_version then
@@ -54,7 +53,7 @@ Gem::Specification.new do |s|
54
53
 
55
54
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
56
55
  s.add_runtime_dependency(%q<hashie>, ["~> 3.4"])
57
- s.add_runtime_dependency(%q<wisper>, ["~> 1.6"])
56
+ s.add_runtime_dependency(%q<wisper>, ["~> 2.0.0.rc1"])
58
57
  s.add_runtime_dependency(%q<locality-uuid>, [">= 0"])
59
58
  s.add_development_dependency(%q<pry>, ["~> 0"])
60
59
  s.add_development_dependency(%q<rspec>, ["~> 2.14"])
@@ -65,7 +64,7 @@ Gem::Specification.new do |s|
65
64
  s.add_development_dependency(%q<rubocop>, ["~> 0.23"])
66
65
  else
67
66
  s.add_dependency(%q<hashie>, ["~> 3.4"])
68
- s.add_dependency(%q<wisper>, ["~> 1.6"])
67
+ s.add_dependency(%q<wisper>, ["~> 2.0.0.rc1"])
69
68
  s.add_dependency(%q<locality-uuid>, [">= 0"])
70
69
  s.add_dependency(%q<pry>, ["~> 0"])
71
70
  s.add_dependency(%q<rspec>, ["~> 2.14"])
@@ -77,7 +76,7 @@ Gem::Specification.new do |s|
77
76
  end
78
77
  else
79
78
  s.add_dependency(%q<hashie>, ["~> 3.4"])
80
- s.add_dependency(%q<wisper>, ["~> 1.6"])
79
+ s.add_dependency(%q<wisper>, ["~> 2.0.0.rc1"])
81
80
  s.add_dependency(%q<locality-uuid>, [">= 0"])
82
81
  s.add_dependency(%q<pry>, ["~> 0"])
83
82
  s.add_dependency(%q<rspec>, ["~> 2.14"])
@@ -1,6 +1,6 @@
1
- require 'pry'
2
1
  require 'forwardable'
3
2
  require 'hashie'
3
+ require 'wisper'
4
4
  require 'locality-uuid'
5
5
 
6
6
  require 'jouba/version'
@@ -20,6 +20,7 @@ module Jouba
20
20
  }
21
21
 
22
22
  class<<self
23
+ include Wisper::Publisher
23
24
  extend Forwardable
24
25
  def_delegators :config, :Key, :Event, :Cache, :Store
25
26
  end
@@ -29,7 +30,10 @@ module Jouba
29
30
  end
30
31
 
31
32
  def emit(key , name , data)
32
- config.Event.new(key: key, name: name, data: data).track
33
+ config.Event.new(key: key, name: name, data: data).tap do |event|
34
+ block_given? ? yield(event) : event.track
35
+ publish(key, event)
36
+ end
33
37
  end
34
38
 
35
39
  def stream(key, params = {})
@@ -1,6 +1,5 @@
1
1
  require 'jouba'
2
2
  require 'jouba/cache'
3
- require 'wisper'
4
3
 
5
4
  module Jouba
6
5
  class Aggregate < Module
@@ -27,10 +26,11 @@ module Jouba
27
26
 
28
27
  module InstanceMethods
29
28
  def emit(name, *args)
30
- event = Jouba.Event.new(key: to_key, name: name, data: args)
31
- apply_event(event)
32
- Jouba.Cache.refresh(to_key, self) { event.track }
33
- publish(event.name, event.data)
29
+ Jouba.emit(to_key, name, args) do |event|
30
+ apply_event(event)
31
+ Jouba.Cache.refresh(to_key, self) { event.track }
32
+ publish(event.name, event.data)
33
+ end
34
34
  end
35
35
 
36
36
  def replay(event)
@@ -1,5 +1,6 @@
1
1
  require 'simplecov'
2
2
  require 'rspec'
3
+ require 'pry'
3
4
 
4
5
  module SimpleCov::Configuration
5
6
  def clean_filters
metadata CHANGED
@@ -1,153 +1,153 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jouba
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - gregory
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-03 00:00:00.000000000 Z
11
+ date: 2015-04-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hashie
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ~>
18
18
  - !ruby/object:Gem::Version
19
19
  version: '3.4'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ~>
25
25
  - !ruby/object:Gem::Version
26
26
  version: '3.4'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: wisper
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ~>
32
32
  - !ruby/object:Gem::Version
33
- version: '1.6'
33
+ version: 2.0.0.rc1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ~>
39
39
  - !ruby/object:Gem::Version
40
- version: '1.6'
40
+ version: 2.0.0.rc1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: locality-uuid
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - '>='
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ">="
52
+ - - '>='
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: pry
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ~>
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ~>
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - "~>"
73
+ - - ~>
74
74
  - !ruby/object:Gem::Version
75
75
  version: '2.14'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - "~>"
80
+ - - ~>
81
81
  - !ruby/object:Gem::Version
82
82
  version: '2.14'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rdoc
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - "~>"
87
+ - - ~>
88
88
  - !ruby/object:Gem::Version
89
89
  version: '3.12'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - "~>"
94
+ - - ~>
95
95
  - !ruby/object:Gem::Version
96
96
  version: '3.12'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: bundler
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - "~>"
101
+ - - ~>
102
102
  - !ruby/object:Gem::Version
103
103
  version: '1.0'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - "~>"
108
+ - - ~>
109
109
  - !ruby/object:Gem::Version
110
110
  version: '1.0'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: jeweler
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - "~>"
115
+ - - ~>
116
116
  - !ruby/object:Gem::Version
117
117
  version: '2.0'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - "~>"
122
+ - - ~>
123
123
  - !ruby/object:Gem::Version
124
124
  version: '2.0'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: simplecov
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - "~>"
129
+ - - ~>
130
130
  - !ruby/object:Gem::Version
131
131
  version: '0'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - "~>"
136
+ - - ~>
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: rubocop
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
- - - "~>"
143
+ - - ~>
144
144
  - !ruby/object:Gem::Version
145
145
  version: '0.23'
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
- - - "~>"
150
+ - - ~>
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0.23'
153
153
  description: 'Jouba is a tool set for event sourcing: aggregate root, entities and
@@ -159,9 +159,9 @@ extra_rdoc_files:
159
159
  - LICENSE.txt
160
160
  - README.md
161
161
  files:
162
- - ".document"
163
- - ".rspec"
164
- - ".rubocop.yml"
162
+ - .document
163
+ - .rspec
164
+ - .rubocop.yml
165
165
  - Gemfile
166
166
  - Gemfile.lock
167
167
  - LICENSE.txt
@@ -193,17 +193,17 @@ require_paths:
193
193
  - lib
194
194
  required_ruby_version: !ruby/object:Gem::Requirement
195
195
  requirements:
196
- - - ">="
196
+ - - '>='
197
197
  - !ruby/object:Gem::Version
198
198
  version: '0'
199
199
  required_rubygems_version: !ruby/object:Gem::Requirement
200
200
  requirements:
201
- - - ">="
201
+ - - '>='
202
202
  - !ruby/object:Gem::Version
203
203
  version: '0'
204
204
  requirements: []
205
205
  rubyforge_project:
206
- rubygems_version: 2.2.2
206
+ rubygems_version: 2.0.14
207
207
  signing_key:
208
208
  specification_version: 4
209
209
  summary: 'Jouba is a tool set for event sourcing: aggregate root, entities and storage'