woyo-world 0.0.8 → 0.0.9

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: 8cbc8a5d94754ea504e7df2e4cee823c172bec1c
4
- data.tar.gz: 3aa4c6addaf017db4ceddfcbba8c062341883444
3
+ metadata.gz: 75a8fb38d8b692c8197acee596c314f553268d8c
4
+ data.tar.gz: b286b86791f363c9195cc7bb17536837f77bfe5d
5
5
  SHA512:
6
- metadata.gz: 0170be24f57b4fe0fbbb0bfb576b63ef8e5d5be4e20c86ee81e639728ae003336b4f4e0d035a27795fb5780b15455b6e591bfa260331af0d13b8cc2ad834ba5d
7
- data.tar.gz: fa95a9aebdd52812b0940d1db8c4f60de33a3212518a5140f09f815018a6b66bec8b345b9c80966146b31ea1e3b1c50af348ed17a906f91773279967dba9717e
6
+ metadata.gz: 528d74579d0b790a09202b6a672c1de363d2369ee7b40a74e0c0f916c3668129a304184c2b37f88f4fdb6cfd71623f3ddaf1e4341b5fe20a6d39faee2803e97d
7
+ data.tar.gz: 8e4f7ee050063b42905ed304185d5394d7064dcd3fc424b5105459e81b20d4ff9e704b224e20038a9125684dc815eb1066d5a9c53b33c0c293df1fae94a9f3ff
@@ -1,4 +1,5 @@
1
1
  require_relative 'world_object'
2
+ require_relative 'location'
2
3
 
3
4
  module Woyo
4
5
 
@@ -7,20 +8,22 @@ class Action < WorldObject
7
8
  def initialize_object
8
9
  super
9
10
  attribute :describe
10
- exclusion :result
11
11
  @proc = proc { nil }
12
12
  end
13
13
 
14
14
  def execute
15
- proc_result = if @proc.arity < 1
15
+ location_or_context.clear_changes
16
+ result = if @proc.arity < 1
16
17
  @context.instance_eval &@proc
17
18
  else
18
19
  @context.instance_exec self, &@proc
19
20
  end
20
- true_members = result.members.select { |member| result[member] }
21
- true_members = true_members[0] if true_members.count == 1
22
- true_members = nil if true_members.empty?
23
- { result: true_members, describe: describe, execution: proc_result }
21
+ unless result.kind_of? Hash
22
+ result = { return: result }
23
+ end
24
+ # result: { location: :place } signals change of location (like going a way!)
25
+ # todo: fill return hash with action attributes, groups, exclusions ? ...
26
+ { describe: describe, result: result, changes: location_or_context.changes }
24
27
  end
25
28
 
26
29
  def execution &block
@@ -31,6 +34,15 @@ class Action < WorldObject
31
34
  end
32
35
  end
33
36
 
37
+ def location_or_context
38
+ ancestor = self
39
+ while ancestor.context do
40
+ return ancestor if ancestor.kind_of? Woyo::Location
41
+ ancestor = ancestor.context
42
+ end
43
+ ancestor
44
+ end
45
+
34
46
  end
35
47
 
36
48
  end
@@ -19,20 +19,57 @@ module Attributes
19
19
  @listeners = {}
20
20
  end
21
21
 
22
- def add_attribute_listener attr, listener
23
- @listeners[attr] = listener
22
+ def add_listener attr, listener
23
+ @listeners[attr] ||= []
24
+ @listeners[attr] << listener
24
25
  end
25
26
 
26
27
  def []= attr, value
27
28
  old_value = self[attr]
28
29
  super
29
- if ( listener = @listeners[attr] ) && value != old_value
30
- listener.notify attr, value
30
+ if value != old_value
31
+ @listeners[attr].each { |listener| listener.notify attr, value } if @listeners[attr] # attribute listeners (groups, etc..)
32
+ @listeners[:*].each { |listener| listener.notify attr, value } if @listeners[:*] # wildcard listeners (trackers)
31
33
  end
32
34
  end
33
35
 
34
36
  end
35
-
37
+
38
+ class ChangesHash < Hash
39
+
40
+ alias_method :names, :keys
41
+ alias_method :set, :[]=
42
+
43
+ def notify attr, value
44
+ self[attr] = value
45
+ end
46
+
47
+ end
48
+
49
+ def changes
50
+ @changes ? @changes.merge!( dependent_changes ) : nil
51
+ end
52
+
53
+ def dependent_changes
54
+ remaining_attrs = @attributes.names - @changes.names
55
+ dependent_attrs = remaining_attrs.select do |attr|
56
+ @attributes[attr].kind_of?( Hash ) && ! ( @attributes[attr].keys & @changes.names ).empty?
57
+ end
58
+ dependent_attrs.each_with_object({}) do |attr,hash|
59
+ hash[attr] = send attr
60
+ end
61
+ end
62
+
63
+ def track_changes
64
+ @changes = ChangesHash.new
65
+ @attributes ||= Woyo::Attributes::AttributesHash.new
66
+ @attributes.add_listener :*, @changes # :* indicates listener for changes to all attributes
67
+ end
68
+
69
+ def clear_changes
70
+ @changes.clear
71
+ end
72
+
36
73
  def attribute *attrs, &block
37
74
  attributes *attrs, &block
38
75
  end
@@ -38,7 +38,7 @@ module Attributes
38
38
  if @members && ! @members.empty?
39
39
  @default = @members.first
40
40
  self[@default] = true
41
- @members.each { |member| @attributes.add_attribute_listener member, self }
41
+ @members.each { |member| @attributes.add_listener member, self }
42
42
  end
43
43
  end
44
44
 
@@ -51,7 +51,7 @@ module Attributes
51
51
  else
52
52
  @attributes.set new_member, false
53
53
  end
54
- @attributes.add_attribute_listener new_member, self
54
+ @attributes.add_listener new_member, self
55
55
  self
56
56
  end
57
57
 
@@ -1,3 +1,3 @@
1
1
  module Woyo
2
- WORLD_VERSION = "0.0.8"
2
+ WORLD_VERSION = "0.0.9"
3
3
  end
@@ -8,8 +8,22 @@ class Way < WorldObject
8
8
  super
9
9
  attribute :going
10
10
  exclusion :passable, :closed, :open # defaults to closed: true
11
+ action :go do
12
+ describe proc { self.context.going }
13
+ #result proc { self.context.passable }
14
+ execution do
15
+ {
16
+ go: open?,
17
+ location: open? ? self.to.id : nil
18
+ }
19
+ end
20
+ end
11
21
  end
12
22
 
23
+ # def go
24
+ # { go: open?, going: self.going }
25
+ # end
26
+
13
27
  def world
14
28
  from ? from.world : nil
15
29
  end
@@ -48,10 +62,6 @@ class Way < WorldObject
48
62
  end
49
63
  end
50
64
 
51
- def go
52
- { go: open?, going: self.going }
53
- end
54
-
55
65
  end
56
66
 
57
67
  end
@@ -16,8 +16,8 @@ class World < WorldObject
16
16
  attributes :start
17
17
  end
18
18
 
19
- def initialize &block
20
- super nil, context: nil, &block
19
+ def initialize id = nil, &block
20
+ super id, context: nil, &block
21
21
  end
22
22
 
23
23
  end
@@ -14,15 +14,52 @@ class WorldObject
14
14
  children :action
15
15
 
16
16
  def initialize id, context: nil, &block
17
- @id = id.to_s.downcase.to_sym
17
+ @id = id ? id.to_s.downcase.to_sym : nil
18
18
  @context = context
19
- attributes :description, name: proc { id.to_s.capitalize }
19
+ attributes :description, name: proc { id.to_s.capitalize.gsub('_',' ') }
20
20
  initialize_object
21
21
  evaluate &block
22
+ # todo:
23
+ # creating attributes should register with change listener
24
+ # this will catch all attributes anytime they are created
25
+ # instead of just after initialize->evaluate
26
+ track_changes
22
27
  end
23
28
 
24
29
  def initialize_object ; end
25
30
 
31
+ def uid
32
+ if @context
33
+ @context.uid + '-' + id.to_s
34
+ else
35
+ id.to_s
36
+ end
37
+ end
38
+
39
+ alias_method :attribute_clear_changes, :clear_changes
40
+ def clear_changes
41
+ attribute_clear_changes
42
+ children.each do |child_type,type_children|
43
+ type_children.each do |child_id,child|
44
+ child.clear_changes
45
+ end
46
+ end
47
+ end
48
+
49
+ alias_method :attribute_changes, :changes
50
+ def changes
51
+ all_changes = attribute_changes
52
+ children.each do |child_type,type_children|
53
+ child_type_changes = {}
54
+ type_children.each do |child_id,child|
55
+ child_changes = child.changes
56
+ child_type_changes[child_id] = child_changes unless child_changes.empty?
57
+ end
58
+ all_changes[child_type] = child_type_changes unless child_type_changes.empty?
59
+ end
60
+ all_changes
61
+ end
62
+
26
63
  end
27
64
 
28
65
  end
@@ -9,24 +9,22 @@
9
9
 
10
10
  - def render_group group_element
11
11
  - group = group_element.values.first
12
- - unless group.first[:hide]
13
- - haml_tag :div do
14
- - group.each do |element|
15
- - case
16
- - when element.keys.first == :head then render_head element, 2
17
- - when element.keys.first == :text then render_text element
18
- - when element.keys.first == :group then render_group element
19
- - when element.keys.first == :example then render_example element
12
+ - haml_tag :div do
13
+ - group.each do |element|
14
+ - case
15
+ - when element.keys.first == :head then render_head element, 2
16
+ - when element.keys.first == :text then render_text element
17
+ - when element.keys.first == :group then render_group element
18
+ - when element.keys.first == :example then render_example element
20
19
 
21
20
  - def render_example example_element
22
21
  - example = example_element.values.first
23
- - unless example.first[:hide]
24
- - haml_tag :div do
25
- - example.each do |element|
26
- - case
27
- - when element.keys.first == :head then render_head element, 3
28
- - when element.keys.first == :text then render_text element
29
- - when element.keys.include?(:code) then render_code element
22
+ - haml_tag :div do
23
+ - example.each do |element|
24
+ - case
25
+ - when element.keys.first == :head then render_head element, 3
26
+ - when element.keys.first == :text then render_text element
27
+ - when element.keys.include?(:code) then render_code element
30
28
 
31
29
  - def render_head head_element, size = 1
32
30
  - case size
@@ -41,9 +39,8 @@
41
39
  - haml_tag :p, text_element.values.first
42
40
 
43
41
  - def render_code code_element
44
- - unless code_element[:hide]
45
- - haml_tag :div do
46
- - haml_tag :pre, "<code>#{preserve(code_element[:code])}#{' #=> ' + code_element[:value].to_s if code_element[:value]}</code>"
42
+ - haml_tag :div do
43
+ - haml_tag :pre, "<code>#{preserve(code_element[:code])}#{' #=> ' + code_element[:value].to_s if code_element[:value]}</code>"
47
44
 
48
45
  %html
49
46
 
@@ -24,7 +24,7 @@ class SpecDocFormatter < RSpec::Core::Formatters::BaseFormatter
24
24
 
25
25
  def stop(examples_notification)
26
26
  # if option[:json]
27
- #output.puts json_format
27
+ # output.puts json_format
28
28
  # end
29
29
  # if option[:haml]
30
30
  output.puts haml_format
@@ -219,10 +219,9 @@ describe 'DSL' do
219
219
 
220
220
  head 'Items'
221
221
 
222
- doc 'stuff here'
223
- # do
224
- # pending
225
- # end
222
+ doc 'stuff here' do
223
+ pending
224
+ end
226
225
 
227
226
  end
228
227
 
@@ -310,20 +309,17 @@ describe 'DSL' do
310
309
  head 'Context'
311
310
  text "Other objects may be referred to in different ways."
312
311
 
313
- doc 'world'
314
- # do
315
- # pending
316
- # end
312
+ doc 'world' do
313
+ pending
314
+ end
317
315
 
318
- doc 'location'
319
- # do
320
- # pending
321
- # end
316
+ doc 'location' do
317
+ pending
318
+ end
322
319
 
323
- doc 'context'
324
- # do
325
- # pending
326
- # end
320
+ doc 'context' do
321
+ pending
322
+ end
327
323
 
328
324
  end
329
325
 
@@ -5,21 +5,21 @@ describe Woyo::Action do
5
5
 
6
6
  let( :action ) { Woyo::Action.new :test }
7
7
 
8
- context 'has exclusions' do
8
+ # context 'has exclusions' do
9
9
 
10
- context ':result' do
10
+ # context ':result' do
11
11
 
12
- it 'exists' do
13
- expect(action.exclusions.names).to include :result
14
- end
12
+ # it 'exists' do
13
+ # expect(action.exclusions.names).to include :result
14
+ # end
15
15
 
16
- it 'has no members' do
17
- expect(action.result.members).to be_empty
18
- end
16
+ # it 'has no members' do
17
+ # expect(action.result.members).to be_empty
18
+ # end
19
19
 
20
- end
20
+ # end
21
21
 
22
- end
22
+ # end
23
23
 
24
24
  context "execution may be defined" do
25
25
 
@@ -30,7 +30,7 @@ describe Woyo::Action do
30
30
 
31
31
  end
32
32
 
33
- context "may be executed" do
33
+ context "executed" do
34
34
 
35
35
  it 'by calling #execution directly' do
36
36
  action.execution { :answer }
@@ -47,14 +47,14 @@ describe Woyo::Action do
47
47
 
48
48
  it 'returns result hash with single values for single truthy result' do
49
49
  action.exclusion :result, :success, :failure
50
- action.execution { |this| this.success! }
50
+ action.execution { |action| action.success! }
51
51
  action.describe success: "Succeeded"
52
- expect(action.execute).to eq( { result: :success, describe: "Succeeded", execution: true } )
52
+ expect(action.execute).to eq( { result: :success, describe: "Succeeded", execution: true, changes: {} } )
53
53
  end
54
54
 
55
55
  it 'returns result hash with empty results for empty result exclusion' do
56
56
  action.describe "Empty"
57
- expect(action.execute).to eq( { result: nil, describe: "Empty", execution: nil } )
57
+ expect(action.execute).to eq( { result: nil, describe: "Empty", execution: nil, changes: {} } )
58
58
  end
59
59
 
60
60
  end
@@ -64,24 +64,48 @@ describe Woyo::Action do
64
64
  it 'returns result hash with single value for single truthy result' do
65
65
  action.group :result, a: false, b: true, c: false
66
66
  action.describe a: 'aaa', b: 'bbb', c: 'ccc'
67
- expect(action.execute).to eq( { result: :b, describe: 'bbb', execution: nil } )
67
+ expect(action.execute).to eq( { result: :b, describe: 'bbb', execution: nil, changes: {} } )
68
68
  end
69
69
 
70
70
  it 'returns result hash with multiple values for multiple truthy results' do
71
71
  action.group :result, a: true, b: false, c: true
72
72
  action.describe a: 'aaa', b: 'bbb', c: 'ccc'
73
- expect(action.execute).to eq( { result: [ :a, :c ], describe: [ 'aaa', 'ccc' ], execution: nil } )
73
+ expect(action.execute).to eq( { result: [ :a, :c ], describe: [ 'aaa', 'ccc' ], execution: nil, changes: {} } )
74
74
  end
75
75
 
76
76
  it 'returns result hash with empty results for empty result group' do
77
77
  action.describe "Empty"
78
- expect(action.execute).to eq( { result: nil, describe: "Empty", execution: nil } )
78
+ expect(action.execute).to eq( { result: nil, describe: "Empty", execution: nil, changes: {} } )
79
79
  end
80
80
 
81
81
  it 'returns result hash with empty results for no truthy results' do
82
82
  action.group :result, a: false, b: false, c: false
83
83
  action.describe "Empty"
84
- expect(action.execute).to eq( { result: nil, describe: "Empty", execution: nil } )
84
+ expect(action.execute).to eq( { result: nil, describe: "Empty", execution: nil, changes: {} } )
85
+ end
86
+
87
+ end
88
+
89
+ context 'with changes' do
90
+
91
+ it 'returns changed attributes' do
92
+ action.attributes :a, :b ,:c
93
+ action.execution { |action| action.a true ; action.b false }
94
+ expect(action.execute[:changes]).to eq( { a: true, b: false } )
95
+ end
96
+
97
+ it 'returns changed attributes for this execution only' do
98
+ action.attributes :a, :b ,:count
99
+ action.execution do |action|
100
+ action.count ||= 0
101
+ action.count += 1
102
+ case action.count
103
+ when 1 then action.a true
104
+ when 2 then action.b true
105
+ end
106
+ end
107
+ expect(action.execute[:changes]).to eq( { count: 1, a: true } )
108
+ expect(action.execute[:changes]).to eq( { count: 2, b: true } )
85
109
  end
86
110
 
87
111
  end
@@ -223,6 +223,64 @@ describe Woyo::Attributes do
223
223
 
224
224
  end
225
225
 
226
+ context 'listeners' do
227
+
228
+ let(:lat) { AttrTest.new }
229
+ let(:listener_class) do
230
+ class AttrListenerTest
231
+ attr_reader :changed_attribute, :changed_value
232
+ def notify attr,value
233
+ @changed_attribute = attr
234
+ @changed_value = value
235
+ end
236
+ end
237
+ AttrListenerTest
238
+ end
239
+
240
+ before :each do
241
+ lat.attribute say: "Hello"
242
+ end
243
+
244
+ it 'are notified of attribute changes' do
245
+ expect(lat.say).to eq "Hello"
246
+ listener = listener_class.new
247
+ lat.attributes.add_listener :say, listener
248
+ lat.say "Bye"
249
+ expect(listener.changed_attribute).to eq :say
250
+ end
251
+
252
+ it 'are not notified if value does not change' do
253
+ expect(lat.say).to eq "Hello"
254
+ listener = listener_class.new
255
+ lat.attributes.add_listener :say, listener
256
+ lat.say "Hello"
257
+ expect(listener.changed_attribute).to be_nil
258
+ end
259
+
260
+ it 'are notified with attribute and value' do
261
+ expect(lat.say).to eq "Hello"
262
+ listener = listener_class.new
263
+ lat.attributes.add_listener :say, listener
264
+ lat.say "Bye"
265
+ expect(listener.changed_attribute).to eq :say
266
+ expect(listener.changed_value).to eq "Bye"
267
+ end
268
+
269
+ it 'may be multiple' do
270
+ expect(lat.say).to eq "Hello"
271
+ listener1 = listener_class.new
272
+ lat.attributes.add_listener :say, listener1
273
+ listener2 = listener_class.new
274
+ lat.attributes.add_listener :say, listener2
275
+ lat.say "Bye"
276
+ expect(listener1.changed_attribute).to eq :say
277
+ expect(listener1.changed_value).to eq "Bye"
278
+ expect(listener2.changed_attribute).to eq :say
279
+ expect(listener2.changed_value).to eq "Bye"
280
+ end
281
+
282
+ end
283
+
226
284
  context 'that are boolean have convenient instance accessors' do
227
285
 
228
286
  let(:bat) { class BooleanAttrTest; include Woyo::Attributes; end.new }
@@ -420,5 +478,52 @@ describe Woyo::Attributes do
420
478
 
421
479
  end
422
480
 
481
+ context 'changes' do
482
+
483
+ let(:cat) { AttrTest.new }
484
+
485
+ before :each do
486
+ cat.attributes :one, :two, :three
487
+ end
488
+
489
+ it 'can be tracked' do
490
+ expect(cat.changes).to eq nil
491
+ cat.track_changes
492
+ expect(cat.changes).to be_instance_of Woyo::Attributes::ChangesHash
493
+ expect(cat.changes).to be_empty
494
+ cat.one = 1
495
+ cat.two = 2
496
+ expect(cat.changes.count).to eq 2
497
+ expect(cat.changes[:one]).to eq 1
498
+ expect(cat.changes[:two]).to eq 2
499
+ end
500
+
501
+ it 'tracking can be cleared' do
502
+ cat.track_changes
503
+ cat.three = 3
504
+ expect(cat.changes[:three]).to eq 3
505
+ cat.clear_changes
506
+ expect(cat.changes).to be_empty
507
+ cat.one = 1
508
+ expect(cat.changes[:one]).to eq 1
509
+ end
510
+
511
+ it 'tracking includes dependent attributes (hashes with attribute keys)' do
512
+ cat.attributes :reaction, :hot, :warm, :cool, :cold
513
+ cat.hot = true
514
+ cat.reaction hot: 'Sweat', warm: 'Relax', cool: 'Huddle', cold: 'Shiver'
515
+ cat.track_changes
516
+ cat.cold = true
517
+ cat.hot = false
518
+ changes = cat.changes
519
+ expect(changes.keys).to include :reaction
520
+ expect(changes[:reaction]).to eq "Shiver"
521
+ expect(changes[:cold]).to eq true
522
+ expect(changes[:hot]).to eq false
523
+ expect(changes.count).to eq 3
524
+ end
525
+
526
+ end
527
+
423
528
  end
424
529
 
@@ -31,12 +31,13 @@ describe Woyo::Attributes::AttributesHash do
31
31
  end
32
32
 
33
33
  it 'registers attribute listeners' do
34
- @attributes.add_attribute_listener :test, @listener
34
+ @attributes.add_listener :test, @listener
35
35
  end
36
36
 
37
- it 'maintains list of attribute listeners' do
37
+ it 'maintains lists of attribute listeners' do
38
38
  expect(@attributes.listeners).to be_kind_of Hash
39
- expect(@attributes.listeners[:test]).to be @listener
39
+ expect(@attributes.listeners[:test]).to be_kind_of Array
40
+ expect(@attributes.listeners[:test].first).to be @listener
40
41
  end
41
42
 
42
43
  it 'notifies listeners of attribute change' do
@@ -52,7 +53,7 @@ describe Woyo::Attributes::AttributesHash do
52
53
  it 'does not notify listener if attribute does not change' do
53
54
  @attributes[:test] = :same_value
54
55
  @listener = Listener.new
55
- @attributes.add_attribute_listener :test, @listener
56
+ @attributes.add_listener :test, @listener
56
57
  expect(@listener.notified).to be false
57
58
  @attributes[:test] = :same_value
58
59
  expect(@listener.notified).to be false
@@ -96,6 +97,11 @@ describe Woyo::Attributes::Group do
96
97
  expect(@group.values).to eq %w( dumb bald smart )
97
98
  end
98
99
 
100
+ it 'change tracking includes group as dependent'# do
101
+ # # simliar method as attributes with hash for value
102
+ # pending
103
+ # end
104
+
99
105
  end
100
106
 
101
107
  describe Woyo::Attributes::Exclusion do
@@ -116,7 +122,7 @@ describe Woyo::Attributes::Exclusion do
116
122
 
117
123
  it 'registers as listener for attributes' do
118
124
  @group.members.each do |member|
119
- expect(@group.attributes.listeners[member]).to be @group
125
+ expect(@group.attributes.listeners[member].first).to be @group
120
126
  end
121
127
  end
122
128
 
@@ -160,4 +166,9 @@ describe Woyo::Attributes::Exclusion do
160
166
  expect(@group.value).to eq :cold
161
167
  end
162
168
 
169
+ it 'change tracking includes group and other changed members as dependent'# do
170
+ # # simliar method as attributes with hash for value
171
+ # pending
172
+ # end
173
+
163
174
  end
@@ -82,15 +82,66 @@ describe Woyo::Location do
82
82
 
83
83
  end
84
84
 
85
- # it '#characters' do
86
- # home = Woyo::Location.new :home do
87
- # character :peter do
88
- # end
89
- # end
90
- # home.characters.size.should eq 1
91
- # peter = home.characters[:peter]
92
- # peter.should be_instance_of Woyo::Character
93
- # peter.location.should be home
94
- # end
85
+ context 'actions' do
86
+
87
+ it 'execute returns changes for location' do
88
+ home = Woyo::Location.new :home do
89
+ item :thing do
90
+ action :make_changes do
91
+ execution do |action|
92
+ name 'Changed item'
93
+ action.name 'Changed action'
94
+ location.name 'Changed location'
95
+ end
96
+ end
97
+ end
98
+ end
99
+ expect(home.item(:thing).action(:make_changes).execute[:changes]).to eq( {
100
+ name: "Changed location",
101
+ item: {
102
+ thing: {
103
+ name: "Changed item",
104
+ action: {
105
+ make_changes: {
106
+ name: "Changed action"
107
+ }
108
+ }
109
+ }
110
+ }
111
+ })
112
+ end
113
+
114
+ it 'execute returns changes for location for this execution only' do
115
+ home = Woyo::Location.new :home do
116
+ item :thing do
117
+ action :make_changes do
118
+ attribute count: 0
119
+ execution do |action|
120
+ action.count += 1
121
+ name "Changed item #{action.count}"
122
+ action.name "Changed action #{action.count}"
123
+ location.name "Changed location #{action.count}"
124
+ end
125
+ end
126
+ action :more_changes do
127
+ execution do |action|
128
+ name "Changed item more"
129
+ action.name "Changed action more"
130
+ location.name "Changed location more"
131
+ end
132
+ end
133
+ end
134
+ end
135
+ expect(home.item(:thing).action(:make_changes).execute[:changes]).to eq( {
136
+ name: "Changed location 1", item: { thing: { name: "Changed item 1", action: { make_changes: { count: 1, name: "Changed action 1" } } } }
137
+ })
138
+ expect(home.item(:thing).action(:make_changes).execute[:changes]).to eq( {
139
+ name: "Changed location 2", item: { thing: { name: "Changed item 2", action: { make_changes: { count: 2, name: "Changed action 2" } } } }
140
+ })
141
+ expect(home.item(:thing).action(:more_changes).execute[:changes]).to eq( {
142
+ name: "Changed location more", item: { thing: { name: "Changed item more", action: { more_changes: { name: "Changed action more" } } } }
143
+ })
144
+ end
145
+ end
95
146
 
96
147
  end
@@ -160,12 +160,12 @@ describe Woyo::Way do
160
160
  end
161
161
 
162
162
  it 'when open' do
163
- expect(@door.go).to eq ( { go: true, going: 'Swings open' } )
163
+ expect(@door.action(:go).execute).to eq ( { describe: 'Swings open', result: { go: true, location: :someplace }, changes: {} } )
164
164
  end
165
165
 
166
166
  it 'when closed' do
167
167
  @door.close!
168
- expect(@door.go).to eq ( { go: false, going: 'Slams shut' } )
168
+ expect(@door.action(:go).execute).to eq ( { describe: 'Slams shut', result: { go: false, location: nil }, changes: {} } )
169
169
  end
170
170
 
171
171
  end
@@ -1,5 +1,6 @@
1
1
  require 'spec_helper'
2
2
  require 'woyo/world/world_object'
3
+ require 'woyo/world/action'
3
4
 
4
5
  describe Woyo::WorldObject do
5
6
 
@@ -43,9 +44,49 @@ describe Woyo::WorldObject do
43
44
 
44
45
  end
45
46
 
46
- it 'provides access to context' do
47
- wo = Woyo::WorldObject.new(:my_id, context: :just_a_test )
48
- expect(wo.context).to eq :just_a_test
47
+ context '#context' do
48
+
49
+ it 'returns parent' do
50
+ class Thing < Woyo::WorldObject ; children :thing ; end
51
+ thing1 = Thing.new :thing1 do
52
+ thing :thing2 do
53
+ thing :thing3
54
+ end
55
+ end
56
+ thing2 = thing1.thing :thing2
57
+ thing3 = thing2.thing :thing3
58
+ expect(thing1.context).to eq nil
59
+ expect(thing2.context).to eq thing1
60
+ expect(thing3.context).to eq thing2
61
+ end
62
+
63
+ end
64
+
65
+ context "#uid" do
66
+
67
+ it 'is object path' do
68
+ class Thing < Woyo::WorldObject ; children :thing ; end
69
+ thing1 = Thing.new :thing1 do
70
+ thing :thing2 do
71
+ thing :thing3
72
+ end
73
+ end
74
+ thing2 = thing1.thing :thing2
75
+ thing3 = thing2.thing :thing3
76
+ expect(thing1.uid).to eq 'thing1'
77
+ expect(thing2.uid).to eq 'thing1-thing2'
78
+ expect(thing3.uid).to eq 'thing1-thing2-thing3'
79
+ end
80
+
81
+ end
82
+
83
+ it 'lists children' do
84
+ class Thing < Woyo::WorldObject ; end
85
+ class Container < Woyo::WorldObject ; children :thing ; end
86
+ box = Container.new :box do
87
+ thing :ball
88
+ end
89
+ expect(box.children).to eq({ thing: { ball: box.thing(:ball) } })
49
90
  end
50
91
 
51
92
  context 'has' do
@@ -91,5 +132,63 @@ describe Woyo::WorldObject do
91
132
 
92
133
  end
93
134
 
135
+ context 'attribute changes' do
136
+
137
+ it 'listed for self' do
138
+ wo = Woyo::WorldObject.new( :thing )
139
+ expect(wo.changes).to be_empty
140
+ wo.name = 'Other'
141
+ expect(wo.changes[:name]).to eq 'Other'
142
+ end
143
+
144
+ it 'list includes dependent changes' do
145
+ wo = Woyo::WorldObject.new( :thing )
146
+ wo.exclusion :color, :red, :blue
147
+ wo.description red: 'Red thing', blue: 'Blue thing'
148
+ wo.changes.clear
149
+ expect(wo.changes).to be_empty
150
+ wo.blue = true
151
+ expect(wo.changes.names).to include :blue
152
+ expect(wo.changes.names).to include :description
153
+ expect(wo.changes[:description]).to eq 'Blue thing'
154
+ end
155
+
156
+ it 'list recursively includes changes for children' do
157
+ class Low < Woyo::WorldObject ; end
158
+ class Mid < Woyo::WorldObject ; children :low ; end
159
+ class Top < Woyo::WorldObject ; children :mid ; end
160
+ t1 = Top.new :t1 do
161
+ mid(:m1) { low :l1 ; low :l2 ; low :l3 }
162
+ mid(:m2) { low :l1 ; low :l2 ; low :l3 }
163
+ mid(:m3) { low :l1 ; low :l2 ; low :l3 }
164
+ mid(:m4) do
165
+ low :l1
166
+ low :l2 do
167
+ exclusion :make_change, :no, :yes
168
+ name no: 'Unchanged l2', yes: 'Changed l2'
169
+ end
170
+ end
171
+ end
172
+ t1.name = 'Changed t1'
173
+ m1 = t1.mid(:m1)
174
+ m2 = t1.mid(:m2)
175
+ m4 = t1.mid(:m4)
176
+ m1.name = 'Changed m1'
177
+ m1.low(:l1).name = "Changed l1"
178
+ m1.low(:l2).name = "Changed l2"
179
+ m2.low(:l2).name = "Changed l2"
180
+ m4.low(:l2).yes = true
181
+ expect(t1.changes).to eq ({
182
+ name: 'Changed t1',
183
+ mid: {
184
+ m1: { name: 'Changed m1', low: { l1: { name: 'Changed l1' }, l2: { name: 'Changed l2' } } },
185
+ m2: { low: { l2: { name: 'Changed l2' } } },
186
+ m4: { low: { l2: { name: 'Changed l2', yes: true } } }
187
+ }
188
+ })
189
+ end
190
+
191
+ end
192
+
94
193
  end
95
194
 
@@ -22,5 +22,15 @@ describe Woyo::World do
22
22
  expect(world.items).to be_empty
23
23
  end
24
24
 
25
+ it 'has no context' do
26
+ expect(world.context).to be_nil
27
+ end
28
+
29
+ it 'has optional id' do
30
+ expect(world.id).to be_nil
31
+ my_world = Woyo::World.new :my_id
32
+ expect(my_world.id).to eq :my_id
33
+ end
34
+
25
35
  end
26
36
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: woyo-world
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerard Fowley
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-03 00:00:00.000000000 Z
11
+ date: 2014-09-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler