event_sourced_record 0.1.3 → 0.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fb56334d7517be8d0816a7f12b91a6c2daf32d6f
4
- data.tar.gz: e7fc402917fad1bb62c5ab3aa25d3f750b824637
3
+ metadata.gz: b0ee2af5ab48feddf17d097471e7298e444b261f
4
+ data.tar.gz: 7b9d4960dfbaaae80abf9f93ed8e640cb1503d01
5
5
  SHA512:
6
- metadata.gz: 7a26c10327b28148eb26819aeda00f56481bd528bedcddd37465b839fcd06da7d08893b99d1aa8821211b84e5491b306f86c02c46cbfce57a6f00f43ef6883e7
7
- data.tar.gz: 2e0608be3b44eda77080c19edbc27d59f11272ffaccf09e433b17147b6bc883672e601d9fbef96746053112d2761ded6aeebd149ad984de58b0da1935e9b4bb8
6
+ metadata.gz: 3c596cb4d97f385ee2827a876f3d1ced7fc180ec80a03ea174aeafceb85269c42662190d486cdd426b6cf561372d3715b5743d1eea7bbea8500d61adb658acd2
7
+ data.tar.gz: b570432fd7e2db6d8fb072031d17475e7bc7579c5beaab175c5d4c752bbba7451700731ddde53f86a8761dc2d417b2a1d245e18236caf34c4de02fa26c5af9bf
data/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ [[[0.2.0]] - Feb 23 2015]
2
+
3
+ * BUGFIX - allow multiple calculators (#11).
4
+ * Included the configuration for the `data` column in the generated Event class
5
+ (#9).
6
+ * Made Event instances immutable (#8).
7
+ * Added `occurred_at` to generated events, which will be used by the calculator
8
+ for ordering events. If `occurred_at` is not defined, `created_at` will be
9
+ used instead (#6).
@@ -1,10 +1,10 @@
1
1
  class EventSourcedRecord::Calculator
2
2
  def self.events(*event_symbols)
3
- @@event_symbols = event_symbols
3
+ @event_symbols = event_symbols
4
4
  end
5
5
 
6
6
  def self.event_classes
7
- @@event_symbols.map { |sym|
7
+ @event_symbols.map { |sym|
8
8
  Module.const_get(sym.to_s.singularize.camelize)
9
9
  }
10
10
  end
@@ -88,13 +88,21 @@ class EventSourcedRecord::Calculator
88
88
  conditions = {projection_name + '_id' => projection.id} if projection
89
89
  end
90
90
  conditions ? event_class.where(conditions).to_a : []
91
- }.flatten.sort_by(&:created_at).reject { |evt|
91
+ }.flatten.sort_by{ |evt| occurrence_time(evt) }.reject { |evt|
92
92
  if last_event_time
93
- evt.created_at > last_event_time
93
+ occurrence_time(evt) > last_event_time
94
94
  end
95
95
  }
96
96
  end
97
97
 
98
+ def occurrence_time(event)
99
+ if event.respond_to?(:occurred_at) && event.occurred_at
100
+ event.occurred_at
101
+ else
102
+ event.created_at
103
+ end
104
+ end
105
+
98
106
  def uuid_field
99
107
  projection_name + '_uuid'
100
108
  end
@@ -9,6 +9,7 @@ module EventSourcedRecord::Event
9
9
  model.after_initialize :ensure_data
10
10
  model.after_initialize :ensure_projection_uuid
11
11
  model.after_initialize :lock_event_type
12
+ model.before_validation :ensure_occurred_at, on: :create
12
13
  model.validates :event_type, presence: true
13
14
  model.validate :validate_corrent_event_type
14
15
  model.validate :validate_by_event_type
@@ -56,6 +57,10 @@ module EventSourcedRecord::Event
56
57
  @event_type_locked = true
57
58
  end
58
59
 
60
+ def ensure_occurred_at
61
+ self.occurred_at = Time.now unless occurred_at
62
+ end
63
+
59
64
  def method_missing(meth, *args, &block)
60
65
  if event_type_config && event_type_config.attributes.include?(meth)
61
66
  ensure_data
@@ -1,3 +1,3 @@
1
1
  module EventSourcedRecord
2
- VERSION = "0.1.3"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -13,7 +13,7 @@ class EventSourcedRecord::EventSourcedRecordGenerator < Rails::Generators::Named
13
13
  def create_event
14
14
  arguments = [
15
15
  "#{file_name}_uuid:string:index", "event_type:string",
16
- "data:text", "created_at:datetime"
16
+ "data:text", "created_at:datetime", "occurred_at:datetime"
17
17
  ].join(' ')
18
18
  generate "event_sourced_record:event", "#{file_name}_event #{arguments}"
19
19
  end
@@ -119,4 +119,21 @@ class EventSourcedRecord::EventTest < MiniTest::Unit::TestCase
119
119
  event.touch
120
120
  end
121
121
  end
122
+
123
+ def test_occurred_at_is_set_if_not_specified
124
+ event = SubscriptionEvent.creation.create!(
125
+ bottles_per_shipment: 1, bottles_purchased: 6, user_id: 999
126
+ )
127
+
128
+ assert event.occurred_at
129
+ end
130
+
131
+ def test_occurred_at_can_be_specified
132
+ event = SubscriptionEvent.creation.new(
133
+ occurred_at: Time.new(2003, 1, 24, 11, 33), bottles_per_shipment: 1,
134
+ bottles_purchased: 6, user_id: 999
135
+ )
136
+
137
+ assert_equal(Time.new(2003, 1, 24, 11, 33), event.occurred_at)
138
+ end
122
139
  end
@@ -16,6 +16,7 @@ class EventSourcedRecord::EventGeneratorTest < Rails::Generators::TestCase
16
16
  event_type:string
17
17
  data:text
18
18
  created_at:datetime
19
+ occurred_at:datetime
19
20
  )
20
21
  end
21
22
 
@@ -23,11 +24,13 @@ class EventSourcedRecord::EventGeneratorTest < Rails::Generators::TestCase
23
24
  ar_major_version = ActiveRecord::VERSION::MAJOR
24
25
  if ar_major_version >= 4
25
26
  assert @generate_calls['migration'].include?(
26
- "create_subscription_events subscription_uuid:string:index event_type:string data:text created_at:datetime"
27
+ "create_subscription_events subscription_uuid:string:index event_type:string data:text created_at:datetime occurred_at:datetime"
27
28
  )
28
29
  else
29
30
  assert_migration("db/migrate/create_subscription_events.rb") do |contents|
30
31
  assert_match(/t.string :event_type/, contents)
32
+ assert_match(/t.datetime :created_at/, contents)
33
+ assert_match(/t.datetime :occurred_at/, contents)
31
34
  end
32
35
  end
33
36
  end
@@ -20,7 +20,7 @@ class EventSourcedRecord::EventSourcedRecordGeneratorTest < Rails::Generators::T
20
20
 
21
21
  test "calls the event generator" do
22
22
  assert @generate_calls['event_sourced_record:event'].include?(
23
- "shampoo_subscription_event shampoo_subscription_uuid:string:index event_type:string data:text created_at:datetime"
23
+ "shampoo_subscription_event shampoo_subscription_uuid:string:index event_type:string data:text created_at:datetime occurred_at:datetime"
24
24
  )
25
25
  end
26
26
 
data/test/test_helper.rb CHANGED
@@ -38,6 +38,7 @@ silence_stream(STDOUT) do
38
38
  t.string "event_type"
39
39
  t.text "data"
40
40
  t.datetime "created_at"
41
+ t.datetime "occurred_at"
41
42
  end
42
43
 
43
44
  create_table "subscriptions", force: true do |t|
@@ -46,6 +47,19 @@ silence_stream(STDOUT) do
46
47
  t.integer "bottles_left"
47
48
  t.string "uuid"
48
49
  end
50
+
51
+ create_table "bottle_events", force: true do |t|
52
+ t.string "bottle_uuid"
53
+ t.string "event_type"
54
+ t.text "data"
55
+ t.datetime "created_at"
56
+ end
57
+
58
+ create_table "bottles", force: true do |t|
59
+ t.integer "volume"
60
+ t.decimal "cost_price"
61
+ t.string "uuid"
62
+ end
49
63
  end
50
64
  end
51
65
 
@@ -90,3 +104,28 @@ class SubscriptionCalculator < EventSourcedRecord::Calculator
90
104
  @subscription.bottles_left -= shipment.num_bottles
91
105
  end
92
106
  end
107
+
108
+ class BottleEvent < ActiveRecord::Base
109
+ include EventSourcedRecord::Event
110
+
111
+ serialize :data
112
+
113
+ event_type :purchase do
114
+ attributes :volume, :cost_price
115
+ end
116
+ end
117
+
118
+ class Bottle < ActiveRecord::Base
119
+ has_many :bottle_events
120
+
121
+ validates :uuid, uniqueness: true
122
+ end
123
+
124
+ class BottleCalculator < EventSourcedRecord::Calculator
125
+ events :bottle_events, :shipments
126
+
127
+ def advance_purchase(event)
128
+ @bottle.volume = event.volume
129
+ @bottle.cost_price = event.cost_price
130
+ end
131
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: event_sourced_record
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Francis Hwang
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-14 00:00:00.000000000 Z
11
+ date: 2015-02-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -160,6 +160,7 @@ files:
160
160
  - ".gitignore"
161
161
  - ".travis.yml"
162
162
  - Appraisals
163
+ - CHANGELOG.md
163
164
  - Gemfile
164
165
  - Getting_Started.md
165
166
  - LICENSE.txt