woyo-world 0.0.8 → 0.0.9

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