metacosm 0.1.4 → 0.1.5

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: 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