metacosm 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c77a542532dce2178b3a6e3c879924724ab83eab
4
- data.tar.gz: 1df7e65cbec1a351789896f8814340c7d0b2ba6f
3
+ metadata.gz: 052e0d6b334fd7502342b5facd9cc6925a466df1
4
+ data.tar.gz: e00f5d01027be65e8f91ff04c8b48665d664eeea
5
5
  SHA512:
6
- metadata.gz: f526c542c046c94a6768a32e9cdd4b4003fe1809dd124978919d781bb6d1f2c17127b34a6c6dda5900f2e6b01127aaef1a6d8b0dc9edbb58aee399502048bc4b
7
- data.tar.gz: efec11ddcc904437cabe20fee6c4f385ff2d197d2d46e648b6853930945ac47582a119de6d89ce47b698e0b06f2036942b0f4f99a0b6ba3148ed181240fb0ac8
6
+ metadata.gz: 4087a92a6eee8aa00cfb280ac6dd2cdba64bdef2b1fda60e29ae5c31d26ebff3a9b2a66c8bcd3c21e3bd5f4b7214c6c3ef2b2007ef897c36ff3710b5cfff5dd2
7
+ data.tar.gz: b008d3c6409925ad9f1d601079dd2805b42fd5709b0245a512e1c183d194f8a8032d5407a465592f909e19359512c2734006efbcd26b3953d5f9a65db7fc8f21
data/README.md CHANGED
@@ -50,16 +50,16 @@ A Fizzbuzz implementation contrived enough to show off many of the features of t
50
50
 
51
51
  protected
52
52
  def fizz
53
- FizzEvent.create(value: @counter, counter_id: @id)
53
+ FizzEvent.create
54
54
  end
55
55
 
56
56
  def buzz
57
- BuzzEvent.create(value: @counter, counter_id: @id)
57
+ BuzzEvent.create
58
58
  end
59
59
 
60
60
  def counter_incremented
61
61
  CounterIncrementedEvent.create(
62
- value: @counter,
62
+ value: @counter,
63
63
  counter_id: @id
64
64
  )
65
65
  end
@@ -73,13 +73,14 @@ A Fizzbuzz implementation contrived enough to show off many of the features of t
73
73
  end
74
74
  end
75
75
 
76
- class IncrementCounterCommand < Struct.new(:increment, :counter_id)
76
+ class IncrementCounterCommand < Command
77
+ attr_accessor :increment, :counter_id
77
78
  end
78
79
 
79
80
  class IncrementCounterCommandHandler
80
- def handle(command)
81
- counter = Counter.find_by(command.counter_id)
82
- counter.increment!(command.increment)
81
+ def handle(increment:,counter_id:)
82
+ counter = Counter.find(counter_id)
83
+ counter.increment!(increment)
83
84
  end
84
85
  end
85
86
 
@@ -97,61 +98,89 @@ A Fizzbuzz implementation contrived enough to show off many of the features of t
97
98
 
98
99
  def update_counter_view(counter_id, value)
99
100
  counter_view = CounterView.where(counter_id: counter_id).first_or_create
100
- counter_view.value = value
101
+ counter_view.update value: value
101
102
  end
102
103
 
103
104
  private
104
105
  def fizz_buzz!(counter_id, n)
105
- fire(FizzCommand.new(counter_id, n)) if fizz?(n)
106
- fire(BuzzCommand.new(counter_id, n)) if buzz?(n)
106
+ fire(FizzCommand.create(counter_id: counter_id)) if fizz?(n)
107
+ fire(BuzzCommand.create(counter_id: counter_id)) if buzz?(n)
107
108
  end
108
109
 
109
110
  def fizz?(n); n % 3 == 0 end
110
111
  def buzz?(n); n % 5 == 0 end
111
112
  end
112
113
 
113
- class FizzCommand < Struct.new(:counter_id, :value); end
114
+ class FizzCommand < Command
115
+ attr_accessor :counter_id
116
+ end
117
+
114
118
  class FizzCommandHandler
115
- def handle(command)
116
- counter = Counter.find_by(command.counter_id)
119
+ def handle(counter_id:)
120
+ counter = Counter.find(counter_id)
117
121
  counter.fizz!
118
122
  end
119
123
  end
120
124
 
121
- class BuzzCommand < Struct.new(:counter_id, :value); end
125
+ class BuzzCommand < Command
126
+ attr_accessor :counter_id
127
+ end
128
+
122
129
  class BuzzCommandHandler
123
- def handle(command)
124
- counter = Counter.find_by(command.counter_id)
130
+ def handle(counter_id:)
131
+ counter = Counter.find(counter_id)
125
132
  counter.buzz!
126
133
  end
127
134
  end
128
135
 
129
136
  class FizzEvent < Event
130
- attr_accessor :value, :counter_id
131
137
  end
132
138
 
133
139
  class FizzEventListener < EventListener
134
- def receive(event)
140
+ def receive
135
141
  puts "fizz"
136
142
  end
137
143
  end
138
144
 
139
145
  class BuzzEvent < Event
140
- attr_accessor :value, :counter_id
141
146
  end
142
147
 
143
148
  class BuzzEventListener < EventListener
144
- def receive(event)
149
+ def receive
145
150
  puts "buzz"
146
151
  end
147
152
  end
153
+ ````
154
+
155
+ Given all this prelude we can run a fizzbuzz "simulation":
156
+
157
+ ````ruby
158
+ sim = Simulation.current
159
+ counter_model = Counter.create
160
+ counter_view = CounterView.find_by(counter_id: counter_model.id)
148
161
 
149
- class CounterValueQuery
150
- def execute(counter_id:)
151
- counter = CounterView.find_by(counter_id: counter_id)
152
- counter.value
153
- end
154
- end
162
+ counter_view.value # => 0
163
+
164
+ increment_counter_command = IncrementCounterCommand.create(
165
+ increment: 1, counter_id: counter_model.id
166
+ )
167
+
168
+ sim.apply(increment_counter_command)
169
+
170
+ counter_view.value # => 1
171
+
172
+ 100.times { sim.apply(increment_counter_command) }
173
+
174
+ sim.events.take(10)
175
+ # => [CounterCreatedEvent (id: 1, counter_id: 1),
176
+ # CounterIncrementedEvent (id: 1, value: 1, counter_id: 1),
177
+ # CounterIncrementedEvent (id: 2, value: 2, counter_id: 1),
178
+ # CounterIncrementedEvent (id: 3, value: 3, counter_id: 1),
179
+ # FizzEvent (id: 1),
180
+ # CounterIncrementedEvent (id: 4, value: 4, counter_id: 1),
181
+ # CounterIncrementedEvent (id: 5, value: 5, counter_id: 1),
182
+ # BuzzEvent (id: 1),
183
+ # CounterIncrementedEvent (id: 6, value: 6, counter_id: 1)]
155
184
  ````
156
185
 
157
186
  ## Requirements
data/gemspec.yml CHANGED
@@ -6,8 +6,8 @@ authors: Joseph Weissman
6
6
  email: jweissman1986@gmail.com
7
7
  homepage: https://rubygems.org/gems/metacosm
8
8
  dependencies:
9
- passive_record: ~> 0.2
10
- frappuccino: ~> 0.3
9
+ passive_record: ~> 0.3
10
+ frappuccino: ~> 0.3
11
11
  development_dependencies:
12
12
  bundler: ~> 1.10
13
13
  codeclimate-test-reporter: ~> 0.1
data/lib/metacosm.rb CHANGED
@@ -6,16 +6,9 @@ module Metacosm
6
6
  class Model
7
7
  include PassiveRecord
8
8
  after_create :register_observer, :emit_creation_event
9
+ after_update :emit_updation_event
9
10
 
10
- def update(attrs={})
11
- attrs.each do |k,v|
12
- send("#{k}=",v)
13
- end
14
-
15
- emit(updation_event(attrs)) if updated_event_class
16
- end
17
-
18
- protected
11
+ private
19
12
  def register_observer
20
13
  Simulation.current.watch(self)
21
14
  end
@@ -24,6 +17,10 @@ module Metacosm
24
17
  emit(creation_event) if created_event_class
25
18
  end
26
19
 
20
+ def emit_updation_event
21
+ emit(updation_event) if updated_event_class
22
+ end
23
+
27
24
  def attributes_with_external_id
28
25
  attrs = to_h
29
26
  if attrs.key?(:id)
@@ -34,7 +31,7 @@ module Metacosm
34
31
  end
35
32
 
36
33
  # trim down extenralized attrs for evt
37
- def attributes_for_event(klass, additional_attrs={})
34
+ def attributes_for_event(klass)
38
35
  # assume evts attrs are attr_accessible?
39
36
  keys_to_keep = klass.instance_methods.find_all do |method|
40
37
  method != :== &&
@@ -43,8 +40,7 @@ module Metacosm
43
40
  end
44
41
 
45
42
  attributes_with_external_id.
46
- delete_if {|k,v| !keys_to_keep.include?(k) }.
47
- merge(additional_attrs)
43
+ delete_if {|k,v| !keys_to_keep.include?(k) }
48
44
  end
49
45
 
50
46
  def assemble_event(klass, addl_attrs={})
@@ -52,7 +48,11 @@ module Metacosm
52
48
  end
53
49
 
54
50
  def creation_event
55
- assemble_event(created_event_class)
51
+ assemble_event created_event_class
52
+ end
53
+
54
+ def updation_event
55
+ assemble_event updated_event_class
56
56
  end
57
57
 
58
58
  def created_event_class
@@ -60,10 +60,6 @@ module Metacosm
60
60
  Object.const_get(created_event_name) rescue nil
61
61
  end
62
62
 
63
- def updation_event(changed_attrs={})
64
- assemble_event(updated_event_class, changed_attrs)
65
- end
66
-
67
63
  def updated_event_class
68
64
  updated_event_name = self.class.name + "UpdatedEvent"
69
65
  Object.const_get(updated_event_name) rescue nil
@@ -0,0 +1,104 @@
1
+ module Metacosm
2
+ module TestHarness
3
+ class GivenWhenThen < Struct.new(:given_events,:when_command,:then_event_class)
4
+ include RSpec::Matchers
5
+
6
+ def when(*commands)
7
+ @when_commands ||= []
8
+ commands.each do |command|
9
+ @when_commands.push command
10
+ end
11
+ self
12
+ end
13
+
14
+ def expect_events(evts)
15
+ @then_events = evts
16
+ verify!
17
+ self
18
+ end
19
+
20
+ def expect_query(query, to_find:)
21
+ @query = query
22
+ @expected_query_results = to_find
23
+ verify!
24
+ self
25
+ end
26
+
27
+ protected
28
+
29
+ def verify!
30
+ clean_slate!
31
+ receive_events!
32
+ fire_commands!
33
+
34
+ validate_events!
35
+ validate_query!
36
+
37
+ self
38
+ end
39
+
40
+ private
41
+
42
+ def clean_slate!
43
+ PassiveRecord.drop_all
44
+ Simulation.current.clear!
45
+ self
46
+ end
47
+
48
+ def receive_events!
49
+ unless self.given_events.nil?
50
+ self.given_events.each do |evt|
51
+ sim.receive(evt, record: false)
52
+ end
53
+ end
54
+ self
55
+ end
56
+
57
+ def fire_commands!
58
+ unless @when_commands.nil?
59
+ @when_commands.each do |cmd|
60
+ sim.apply(cmd)
61
+ end
62
+ end
63
+ self
64
+ end
65
+
66
+ def validate_events!
67
+ if @then_event_class
68
+ expect(@then_event_class).to eq(sim.events.last.class)
69
+ end
70
+
71
+ if @then_events
72
+ expect(@then_events).to match_array(sim.events)
73
+ end
74
+
75
+ if @then_event_attrs
76
+ @then_event_attrs.each do |k,v|
77
+ expect(sim.events.last.send(k)).to eq(v)
78
+ end
79
+ end
80
+
81
+ self
82
+ end
83
+
84
+ def validate_query!
85
+ if @query
86
+ expect(@query.execute).to eq(@expected_query_results)
87
+ end
88
+ self
89
+ end
90
+
91
+ def sim
92
+ @sim ||= Simulation.current
93
+ end
94
+ end
95
+
96
+ def given_no_activity
97
+ GivenWhenThen.new
98
+ end
99
+
100
+ def given_events(events)
101
+ GivenWhenThen.new(events)
102
+ end
103
+ end
104
+ end
@@ -1,4 +1,4 @@
1
1
  module Metacosm
2
2
  # metacosm version
3
- VERSION = "0.1.3"
3
+ VERSION = "0.1.4"
4
4
  end
@@ -12,6 +12,37 @@ describe "a simple simulation (fizzbuzz)" do
12
12
  )
13
13
  end
14
14
 
15
+ it 'should run the linearized test for the README' do
16
+ sim = Simulation.current
17
+ counter_model = Counter.create
18
+ counter_view = CounterView.find_by(counter_id: counter_model.id)
19
+
20
+ expect(counter_view.value).to eq(0) # => 0
21
+
22
+ increment_counter_command = IncrementCounterCommand.create(
23
+ increment: 1, counter_id: counter_model.id
24
+ )
25
+
26
+ sim.apply(increment_counter_command)
27
+
28
+ # model is updated which triggers view changes
29
+ expect(counter_view.value).to eq(1) # => 1
30
+
31
+ 100.times { sim.apply(increment_counter_command) }
32
+
33
+ expect(sim.events.take(10).map(&:class)).to eq(
34
+ [CounterCreatedEvent,
35
+ CounterCreatedEvent,
36
+ CounterIncrementedEvent,
37
+ CounterIncrementedEvent,
38
+ CounterIncrementedEvent,
39
+ FizzEvent,
40
+ CounterIncrementedEvent,
41
+ CounterIncrementedEvent,
42
+ BuzzEvent,
43
+ CounterIncrementedEvent])
44
+ end
45
+
15
46
  context "one command once" do
16
47
  before { simulation.apply(increment_counter) }
17
48
 
data/spec/spec_helper.rb CHANGED
@@ -4,117 +4,13 @@ require 'rspec/its'
4
4
  require 'pry'
5
5
  require 'ostruct'
6
6
  require 'metacosm'
7
+ require 'metacosm/support/test_harness'
7
8
 
8
9
  include Metacosm
9
10
 
10
11
  require 'support/fizz_buzz'
11
12
  require 'support/village'
12
13
 
13
- class GivenWhenThen < Struct.new(:given_events,:when_command,:then_event_class)
14
- include RSpec::Matchers
15
-
16
- def when(*commands)
17
- @when_commands ||= []
18
- commands.each do |command|
19
- @when_commands.push command
20
- end
21
- self
22
- end
23
-
24
- def expect_events(evts)
25
- @then_events = evts
26
- verify!
27
- self
28
- end
29
-
30
- def expect_query(query, to_find:)
31
- @query = query
32
- @expected_query_results = to_find
33
- verify!
34
- self
35
- end
36
-
37
- protected
38
-
39
- def verify!
40
- clean_slate!
41
- receive_events!
42
- fire_commands!
43
-
44
- validate_events!
45
- validate_query!
46
-
47
- self
48
- end
49
-
50
- private
51
-
52
- def clean_slate!
53
- PassiveRecord.drop_all
54
- Simulation.current.clear!
55
- self
56
- end
57
-
58
- def receive_events!
59
- unless self.given_events.nil?
60
- self.given_events.each do |evt|
61
- sim.receive(evt, record: false)
62
- end
63
- end
64
- self
65
- end
66
-
67
- def fire_commands!
68
- unless @when_commands.nil?
69
- @when_commands.each do |cmd|
70
- sim.apply(cmd)
71
- end
72
- end
73
- self
74
- end
75
-
76
- def validate_events!
77
- if @then_event_class
78
- expect(@then_event_class).to eq(sim.events.last.class)
79
- end
80
-
81
- if @then_events
82
- expect(@then_events).to match_array(sim.events)
83
- end
84
-
85
- if @then_event_attrs
86
- @then_event_attrs.each do |k,v|
87
- expect(sim.events.last.send(k)).to eq(v)
88
- end
89
- end
90
-
91
- self
92
- end
93
-
94
- def validate_query!
95
- if @query
96
- expect(@query.execute).to eq(@expected_query_results)
97
- end
98
- self
99
- end
100
-
101
- def sim
102
- @sim ||= Simulation.current
103
- end
104
- end
105
-
106
- module Metacosm
107
- module SpecHelpers
108
- def given_no_activity
109
- GivenWhenThen.new
110
- end
111
-
112
- def given_events(events)
113
- GivenWhenThen.new(events)
114
- end
115
- end
116
- end
117
-
118
14
  RSpec.configure do |c|
119
- c.include Metacosm::SpecHelpers
15
+ c.include Metacosm::TestHarness
120
16
  end
@@ -36,9 +36,15 @@ end
36
36
 
37
37
  class CounterView < View
38
38
  attr_accessor :value, :counter_id
39
- def update_value(new_value)
40
- @value = new_value
41
- self
39
+ end
40
+
41
+ class CounterCreatedEvent < Event
42
+ attr_accessor :counter_id #, :value
43
+ end
44
+
45
+ class CounterCreatedEventListener < EventListener
46
+ def receive(counter_id:)
47
+ CounterView.create(counter_id: counter_id, value: 0)
42
48
  end
43
49
  end
44
50
 
@@ -67,7 +73,7 @@ class CounterIncrementedEventListener < EventListener
67
73
 
68
74
  def update_counter_view(counter_id, value)
69
75
  counter_view = CounterView.where(counter_id: counter_id).first_or_create
70
- counter_view.value = value
76
+ counter_view.update value: value
71
77
  end
72
78
 
73
79
  private
@@ -102,8 +108,7 @@ class BuzzCommandHandler
102
108
  end
103
109
  end
104
110
 
105
- class FizzEvent < Event
106
- end
111
+ class FizzEvent < Event; end
107
112
 
108
113
  class FizzEventListener < EventListener
109
114
  def receive
@@ -111,8 +116,7 @@ class FizzEventListener < EventListener
111
116
  end
112
117
  end
113
118
 
114
- class BuzzEvent < Event
115
- end
119
+ class BuzzEvent < Event; end
116
120
 
117
121
  class BuzzEventListener < EventListener
118
122
  def receive
@@ -80,7 +80,6 @@ class VillageUpdatedEventListener < EventListener
80
80
  end
81
81
  end
82
82
 
83
-
84
83
  class CreatePersonCommand < Command
85
84
  attr_accessor :world_id, :village_id, :person_id, :person_name
86
85
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metacosm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joseph Weissman
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-23 00:00:00.000000000 Z
11
+ date: 2016-02-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: passive_record
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.2'
19
+ version: '0.3'
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
- version: '0.2'
26
+ version: '0.3'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: frappuccino
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -162,6 +162,7 @@ files:
162
162
  - features/step_definitions/metacosm_steps.rb
163
163
  - gemspec.yml
164
164
  - lib/metacosm.rb
165
+ - lib/metacosm/support/test_harness.rb
165
166
  - lib/metacosm/version.rb
166
167
  - metacosm.gemspec
167
168
  - schema.png