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 +4 -4
- data/lib/woyo/world/action.rb +18 -6
- data/lib/woyo/world/attributes.rb +42 -5
- data/lib/woyo/world/group.rb +2 -2
- data/lib/woyo/world/version.rb +1 -1
- data/lib/woyo/world/way.rb +14 -4
- data/lib/woyo/world/world.rb +2 -2
- data/lib/woyo/world/world_object.rb +39 -2
- data/spec/spec_doc.haml +15 -18
- data/spec/spec_doc_formatter.rb +1 -1
- data/spec/woyo/dsl/dsl_spec.rb +12 -16
- data/spec/woyo/world/action_spec.rb +42 -18
- data/spec/woyo/world/attributes_spec.rb +105 -0
- data/spec/woyo/world/group_spec.rb +16 -5
- data/spec/woyo/world/location_spec.rb +61 -10
- data/spec/woyo/world/way_spec.rb +2 -2
- data/spec/woyo/world/world_object_spec.rb +102 -3
- data/spec/woyo/world/world_spec.rb +10 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 75a8fb38d8b692c8197acee596c314f553268d8c
|
4
|
+
data.tar.gz: b286b86791f363c9195cc7bb17536837f77bfe5d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 528d74579d0b790a09202b6a672c1de363d2369ee7b40a74e0c0f916c3668129a304184c2b37f88f4fdb6cfd71623f3ddaf1e4341b5fe20a6d39faee2803e97d
|
7
|
+
data.tar.gz: 8e4f7ee050063b42905ed304185d5394d7064dcd3fc424b5105459e81b20d4ff9e704b224e20038a9125684dc815eb1066d5a9c53b33c0c293df1fae94a9f3ff
|
data/lib/woyo/world/action.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
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
|
23
|
-
@listeners[attr]
|
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
|
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
|
data/lib/woyo/world/group.rb
CHANGED
@@ -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.
|
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.
|
54
|
+
@attributes.add_listener new_member, self
|
55
55
|
self
|
56
56
|
end
|
57
57
|
|
data/lib/woyo/world/version.rb
CHANGED
data/lib/woyo/world/way.rb
CHANGED
@@ -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
|
data/lib/woyo/world/world.rb
CHANGED
@@ -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
|
data/spec/spec_doc.haml
CHANGED
@@ -9,24 +9,22 @@
|
|
9
9
|
|
10
10
|
- def render_group group_element
|
11
11
|
- group = group_element.values.first
|
12
|
-
-
|
13
|
-
-
|
14
|
-
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
-
-
|
24
|
-
-
|
25
|
-
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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
|
-
-
|
45
|
-
- haml_tag :
|
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
|
|
data/spec/spec_doc_formatter.rb
CHANGED
data/spec/woyo/dsl/dsl_spec.rb
CHANGED
@@ -219,10 +219,9 @@ describe 'DSL' do
|
|
219
219
|
|
220
220
|
head 'Items'
|
221
221
|
|
222
|
-
doc 'stuff here'
|
223
|
-
|
224
|
-
|
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
|
-
|
315
|
-
|
316
|
-
# end
|
312
|
+
doc 'world' do
|
313
|
+
pending
|
314
|
+
end
|
317
315
|
|
318
|
-
doc 'location'
|
319
|
-
|
320
|
-
|
321
|
-
# end
|
316
|
+
doc 'location' do
|
317
|
+
pending
|
318
|
+
end
|
322
319
|
|
323
|
-
doc 'context'
|
324
|
-
|
325
|
-
|
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
|
-
|
10
|
+
# context ':result' do
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
# it 'exists' do
|
13
|
+
# expect(action.exclusions.names).to include :result
|
14
|
+
# end
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
# it 'has no members' do
|
17
|
+
# expect(action.result.members).to be_empty
|
18
|
+
# end
|
19
19
|
|
20
|
-
|
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 "
|
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 { |
|
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.
|
34
|
+
@attributes.add_listener :test, @listener
|
35
35
|
end
|
36
36
|
|
37
|
-
it 'maintains
|
37
|
+
it 'maintains lists of attribute listeners' do
|
38
38
|
expect(@attributes.listeners).to be_kind_of Hash
|
39
|
-
expect(@attributes.listeners[:test]).to
|
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.
|
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
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
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
|
data/spec/woyo/world/way_spec.rb
CHANGED
@@ -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,
|
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,
|
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
|
-
|
47
|
-
|
48
|
-
|
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.
|
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-
|
11
|
+
date: 2014-09-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|