metacosm 0.1.4 → 0.1.5

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: 052e0d6b334fd7502342b5facd9cc6925a466df1
4
- data.tar.gz: e00f5d01027be65e8f91ff04c8b48665d664eeea
3
+ metadata.gz: 26c2c480e58c0185a99b3a80b500591da5ecdc90
4
+ data.tar.gz: a6b9ceed179df3805c430fa33297da1c85bd834d
5
5
  SHA512:
6
- metadata.gz: 4087a92a6eee8aa00cfb280ac6dd2cdba64bdef2b1fda60e29ae5c31d26ebff3a9b2a66c8bcd3c21e3bd5f4b7214c6c3ef2b2007ef897c36ff3710b5cfff5dd2
7
- data.tar.gz: b008d3c6409925ad9f1d601079dd2805b42fd5709b0245a512e1c183d194f8a8032d5407a465592f909e19359512c2734006efbcd26b3953d5f9a65db7fc8f21
6
+ metadata.gz: b763778df53c6c589127402ab24a432c1c56dc91769bad50951191e4a0042eee173767f6a2de90b2a182d8e02750b88dbc8fbef509d2edccdc124ac8b491fc8c
7
+ data.tar.gz: cc70b16c39fd0332363b45020a201ce1db30be50416c8cba0ac0bca6d9ac0a4f36f7c5e693ecce1317ca31634c3b8fca7b885e63632028e759136bcc0d43a6aa
data/lib/metacosm.rb CHANGED
@@ -1,75 +1,11 @@
1
1
  require 'passive_record'
2
2
  require 'frappuccino'
3
+
3
4
  require 'metacosm/version'
5
+ require 'metacosm/model'
6
+ require 'metacosm/simulation'
4
7
 
5
8
  module Metacosm
6
- class Model
7
- include PassiveRecord
8
- after_create :register_observer, :emit_creation_event
9
- after_update :emit_updation_event
10
-
11
- private
12
- def register_observer
13
- Simulation.current.watch(self)
14
- end
15
-
16
- def emit_creation_event
17
- emit(creation_event) if created_event_class
18
- end
19
-
20
- def emit_updation_event
21
- emit(updation_event) if updated_event_class
22
- end
23
-
24
- def attributes_with_external_id
25
- attrs = to_h
26
- if attrs.key?(:id)
27
- new_id_key = self.class.name.split('::').last.underscore + "_id"
28
- attrs[new_id_key.to_sym] = attrs.delete(:id)
29
- end
30
- attrs
31
- end
32
-
33
- # trim down extenralized attrs for evt
34
- def attributes_for_event(klass)
35
- # assume evts attrs are attr_accessible?
36
- keys_to_keep = klass.instance_methods.find_all do |method|
37
- method != :== &&
38
- method != :! &&
39
- klass.instance_methods.include?(:"#{method}=")
40
- end
41
-
42
- attributes_with_external_id.
43
- delete_if {|k,v| !keys_to_keep.include?(k) }
44
- end
45
-
46
- def assemble_event(klass, addl_attrs={})
47
- klass.create(attributes_for_event(klass).merge(addl_attrs))
48
- end
49
-
50
- def creation_event
51
- assemble_event created_event_class
52
- end
53
-
54
- def updation_event
55
- assemble_event updated_event_class
56
- end
57
-
58
- def created_event_class
59
- created_event_name = self.class.name + "CreatedEvent"
60
- Object.const_get(created_event_name) rescue nil
61
- end
62
-
63
- def updated_event_class
64
- updated_event_name = self.class.name + "UpdatedEvent"
65
- Object.const_get(updated_event_name) rescue nil
66
- end
67
-
68
- def blacklisted_attribute_names
69
- [ :@observer_peers ]
70
- end
71
- end
72
-
73
9
  class View
74
10
  include PassiveRecord
75
11
  end
@@ -103,53 +39,4 @@ module Metacosm
103
39
  self.simulation.apply(command)
104
40
  end
105
41
  end
106
-
107
- class Simulation
108
- def watch(model)
109
- Frappuccino::Stream.new(model).on_value(&method(:receive))
110
- end
111
-
112
- def apply(command)
113
- handler_for(command).handle(command.attrs)
114
- end
115
-
116
- def receive(event, record: true)
117
- events.push(event) if record
118
-
119
- listener = listener_for(event)
120
- if event.attrs.any?
121
- listener.receive(event.attrs)
122
- else
123
- listener.receive
124
- end
125
- end
126
-
127
- def events
128
- @events ||= []
129
- end
130
-
131
- def self.current
132
- @current ||= new
133
- end
134
-
135
- def clear!
136
- @events = []
137
- end
138
-
139
- protected
140
- def handler_for(command)
141
- @handlers ||= {}
142
- @handlers[command] ||= Object.const_get(command.class.name.split('::').last + "Handler").new
143
- end
144
-
145
- def listener_for(event)
146
- @listeners ||= {}
147
- @listeners[event] ||= construct_listener_for(event)
148
- end
149
-
150
- def construct_listener_for(event)
151
- listener = Object.const_get(event.class.name.split('::').last + "Listener").new(self)
152
- listener
153
- end
154
- end
155
42
  end
@@ -0,0 +1,68 @@
1
+ module Metacosm
2
+ class Model
3
+ include PassiveRecord
4
+ after_create :register_observer, :emit_creation_event
5
+ after_update :emit_updation_event
6
+
7
+ private
8
+ def register_observer
9
+ Simulation.current.watch(self)
10
+ end
11
+
12
+ def emit_creation_event
13
+ emit(creation_event) if created_event_class
14
+ end
15
+
16
+ def emit_updation_event
17
+ emit(updation_event) if updated_event_class
18
+ end
19
+
20
+ def attributes_with_external_id
21
+ attrs = to_h
22
+ if attrs.key?(:id)
23
+ new_id_key = self.class.name.split('::').last.underscore + "_id"
24
+ attrs[new_id_key.to_sym] = attrs.delete(:id)
25
+ end
26
+ attrs
27
+ end
28
+
29
+ # trim down extenralized attrs for evt
30
+ def attributes_for_event(klass)
31
+ # assume evts attrs are attr_accessible?
32
+ keys_to_keep = klass.instance_methods.find_all do |method|
33
+ method != :== &&
34
+ method != :! &&
35
+ klass.instance_methods.include?(:"#{method}=")
36
+ end
37
+
38
+ attributes_with_external_id.
39
+ delete_if {|k,v| !keys_to_keep.include?(k) }
40
+ end
41
+
42
+ def assemble_event(klass, addl_attrs={})
43
+ klass.create(attributes_for_event(klass).merge(addl_attrs))
44
+ end
45
+
46
+ def creation_event
47
+ assemble_event created_event_class
48
+ end
49
+
50
+ def updation_event
51
+ assemble_event updated_event_class
52
+ end
53
+
54
+ def created_event_class
55
+ created_event_name = self.class.name + "CreatedEvent"
56
+ Object.const_get(created_event_name) rescue nil
57
+ end
58
+
59
+ def updated_event_class
60
+ updated_event_name = self.class.name + "UpdatedEvent"
61
+ Object.const_get(updated_event_name) rescue nil
62
+ end
63
+
64
+ def blacklisted_attribute_names
65
+ [ :@observer_peers ]
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,50 @@
1
+ module Metacosm
2
+ class Simulation
3
+ def watch(model)
4
+ Frappuccino::Stream.new(model).on_value(&method(:receive))
5
+ end
6
+
7
+ def apply(command)
8
+ handler_for(command).handle(command.attrs)
9
+ end
10
+
11
+ def receive(event, record: true)
12
+ events.push(event) if record
13
+
14
+ listener = listener_for(event)
15
+ if event.attrs.any?
16
+ listener.receive(event.attrs)
17
+ else
18
+ listener.receive
19
+ end
20
+ end
21
+
22
+ def events
23
+ @events ||= []
24
+ end
25
+
26
+ def self.current
27
+ @current ||= new
28
+ end
29
+
30
+ def clear!
31
+ @events = []
32
+ end
33
+
34
+ protected
35
+ def handler_for(command)
36
+ @handlers ||= {}
37
+ @handlers[command] ||= Object.const_get(command.class.name.split('::').last + "Handler").new
38
+ end
39
+
40
+ def listener_for(event)
41
+ @listeners ||= {}
42
+ @listeners[event] ||= construct_listener_for(event)
43
+ end
44
+
45
+ def construct_listener_for(event)
46
+ listener = Object.const_get(event.class.name.split('::').last + "Listener").new(self)
47
+ listener
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,21 @@
1
+ RSpec::Matchers.define :trigger_event do |event|
2
+ match do |command|
3
+ # PassiveRecord.drop_all
4
+ Simulation.current.clear!
5
+ Simulation.current.apply(command)
6
+ expect(Simulation.current.events).to include(event)
7
+ end
8
+ end
9
+
10
+ RSpec::Matchers.define :trigger_events do |*events|
11
+ match do |command|
12
+ # PassiveRecord.drop_all
13
+ Simulation.current.clear!
14
+
15
+ Simulation.current.apply(command)
16
+
17
+ events.each do |event|
18
+ expect(Simulation.current.events).to include(event)
19
+ end
20
+ end
21
+ end
@@ -1,4 +1,4 @@
1
1
  module Metacosm
2
2
  # metacosm version
3
- VERSION = "0.1.4"
3
+ VERSION = "0.1.5"
4
4
  end
@@ -12,11 +12,16 @@ describe "a simple simulation (fizzbuzz)" do
12
12
  )
13
13
  end
14
14
 
15
+ let(:counter_incremented) do
16
+ CounterIncrementedEvent.create(
17
+ counter_id: model.id, value: 1
18
+ )
19
+ end
20
+
15
21
  it 'should run the linearized test for the README' do
16
22
  sim = Simulation.current
17
23
  counter_model = Counter.create
18
24
  counter_view = CounterView.find_by(counter_id: counter_model.id)
19
-
20
25
  expect(counter_view.value).to eq(0) # => 0
21
26
 
22
27
  increment_counter_command = IncrementCounterCommand.create(
@@ -41,7 +46,7 @@ describe "a simple simulation (fizzbuzz)" do
41
46
  CounterIncrementedEvent,
42
47
  BuzzEvent,
43
48
  CounterIncrementedEvent])
44
- end
49
+ end
45
50
 
46
51
  context "one command once" do
47
52
  before { simulation.apply(increment_counter) }
@@ -66,6 +71,12 @@ describe "a simple simulation (fizzbuzz)" do
66
71
  end
67
72
  end
68
73
 
74
+ context "one command once (spec harness style)" do
75
+ before { model }
76
+ subject(:command) { increment_counter }
77
+ it { is_expected.to trigger_event(counter_incremented) }
78
+ end
79
+
69
80
  context "one command ten times" do
70
81
  it 'is expected to play fizz buzz' do
71
82
  expect {
@@ -96,12 +107,12 @@ describe "a simple simulation (fizzbuzz)" do
96
107
  counter_value_query.execute(counter_id: model.id)
97
108
  end
98
109
 
99
- it { is_expected.to eq(n) } #"The counter is at 1") }
110
+ it { is_expected.to eq(n) }
100
111
  end
101
112
  end
102
113
 
103
114
  context 'with concurrent command sources' do
104
- let(:m) { 2 } # fibers
115
+ let(:m) { 5 }
105
116
  let(:threads) {
106
117
  ts = []
107
118
  m.times do
@@ -145,8 +156,8 @@ describe "a more complex simulation (village)" do
145
156
 
146
157
  describe "#apply" do
147
158
  context 'create and populate villages' do
148
- let(:person_id) { 'person_id' }
149
- let(:village_id) { 'village_id' }
159
+ let(:person_id) { 'person_id' }
160
+ let(:village_id) { 'village_id' }
150
161
  let(:village_name) { 'Oakville Ridge' }
151
162
 
152
163
  let(:people_per_village) { 10 }
data/spec/spec_helper.rb CHANGED
@@ -5,6 +5,7 @@ require 'pry'
5
5
  require 'ostruct'
6
6
  require 'metacosm'
7
7
  require 'metacosm/support/test_harness'
8
+ require 'metacosm/support/spec_harness'
8
9
 
9
10
  include Metacosm
10
11
 
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.4
4
+ version: 0.1.5
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-24 00:00:00.000000000 Z
11
+ date: 2016-02-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: passive_record
@@ -162,6 +162,9 @@ files:
162
162
  - features/step_definitions/metacosm_steps.rb
163
163
  - gemspec.yml
164
164
  - lib/metacosm.rb
165
+ - lib/metacosm/model.rb
166
+ - lib/metacosm/simulation.rb
167
+ - lib/metacosm/support/spec_harness.rb
165
168
  - lib/metacosm/support/test_harness.rb
166
169
  - lib/metacosm/version.rb
167
170
  - metacosm.gemspec