compo 0.1.0
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 +7 -0
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/CHANGELOG +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +7 -0
- data/compo.gemspec +33 -0
- data/lib/compo/array_composite.rb +103 -0
- data/lib/compo/composite.rb +130 -0
- data/lib/compo/hash_composite.rb +70 -0
- data/lib/compo/leaf.rb +22 -0
- data/lib/compo/movable.rb +53 -0
- data/lib/compo/null_composite.rb +63 -0
- data/lib/compo/parent_tracker.rb +64 -0
- data/lib/compo/version.rb +4 -0
- data/lib/compo.rb +12 -0
- data/spec/array_composite_spec.rb +225 -0
- data/spec/composite_spec.rb +249 -0
- data/spec/hash_composite_spec.rb +184 -0
- data/spec/leaf_spec.rb +14 -0
- data/spec/movable_spec.rb +201 -0
- data/spec/null_composite_spec.rb +67 -0
- data/spec/parent_tracker_spec.rb +63 -0
- data/spec/spec_helper.rb +11 -0
- metadata +192 -0
@@ -0,0 +1,201 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'compo'
|
3
|
+
|
4
|
+
# Mock implementation of a Movable
|
5
|
+
class MockMovable
|
6
|
+
include Compo::Movable
|
7
|
+
end
|
8
|
+
|
9
|
+
describe MockMovable do
|
10
|
+
let(:old_parent) { double(:old_parent) }
|
11
|
+
let(:new_parent) { double(:new_parent) }
|
12
|
+
|
13
|
+
describe '#move_to' do
|
14
|
+
context 'when the receiving parent is nil' do
|
15
|
+
context 'and the Movable has no parent' do
|
16
|
+
before(:each) do
|
17
|
+
allow(subject).to receive(:parent).and_return(nil)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'returns itself' do
|
21
|
+
expect(subject.move_to(nil, :test)).to eq(subject)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'calls #parent' do
|
25
|
+
expect(subject).to receive(:parent).once
|
26
|
+
subject.move_to(nil, :test)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'and the Movable has a parent' do
|
31
|
+
before(:each) do
|
32
|
+
allow(subject).to receive(:parent).and_return(old_parent)
|
33
|
+
allow(old_parent).to receive(:remove)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'returns itself' do
|
37
|
+
expect(subject.move_to(nil, :test)).to eq(subject)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'calls #parent' do
|
41
|
+
expect(subject).to receive(:parent)
|
42
|
+
subject.move_to(nil, :test)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'calls #remove on the old parent with the Movable' do
|
46
|
+
expect(old_parent).to receive(:remove).once.with(subject)
|
47
|
+
subject.move_to(nil, :test)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'when the receiving parent refuses to add the Movable' do
|
53
|
+
before(:each) do
|
54
|
+
allow(new_parent).to receive(:add).and_return(nil)
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'and the Movable has no parent' do
|
58
|
+
before(:each) do
|
59
|
+
allow(subject).to receive(:parent).and_return(nil)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'returns itself' do
|
63
|
+
expect(subject.move_to(new_parent, :test)).to eq(subject)
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'calls #parent' do
|
67
|
+
expect(subject).to receive(:parent)
|
68
|
+
subject.move_to(new_parent, :test)
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'calls #add on the new parent with the ID and Movable' do
|
72
|
+
expect(new_parent).to receive(:add).once.with(:test, subject)
|
73
|
+
subject.move_to(new_parent, :test)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context 'and the Movable has a parent that refuses to remove it' do
|
78
|
+
before(:each) do
|
79
|
+
allow(subject).to receive(:parent).and_return(old_parent)
|
80
|
+
allow(old_parent).to receive(:remove).and_return(nil)
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'returns itself' do
|
84
|
+
expect(subject.move_to(new_parent, :test)).to eq(subject)
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'calls #parent' do
|
88
|
+
expect(subject).to receive(:parent)
|
89
|
+
subject.move_to(new_parent, :test)
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'calls #remove on the old parent with the Movable' do
|
93
|
+
expect(old_parent).to receive(:remove).once.with(subject)
|
94
|
+
subject.move_to(new_parent, :test)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context 'and the Movable has a parent that allows it to be removed' do
|
99
|
+
before(:each) do
|
100
|
+
allow(subject).to receive(:parent).and_return(old_parent)
|
101
|
+
allow(old_parent).to receive(:remove).and_return(subject)
|
102
|
+
allow(new_parent).to receive(:add)
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'returns itself' do
|
106
|
+
expect(subject.move_to(new_parent, :test)).to eq(subject)
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'calls #parent' do
|
110
|
+
expect(subject).to receive(:parent)
|
111
|
+
subject.move_to(new_parent, :test)
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'calls #remove on the old parent with the Movable' do
|
115
|
+
expect(old_parent).to receive(:remove).once.with(subject)
|
116
|
+
subject.move_to(new_parent, :test)
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'calls #add on the new parent with the ID and Movable' do
|
120
|
+
expect(new_parent).to receive(:add).once.with(:test, subject)
|
121
|
+
subject.move_to(new_parent, :test)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
context 'when the receiving parent allows the Movable to be added' do
|
127
|
+
before(:each) do
|
128
|
+
allow(new_parent).to receive(:add).and_return(subject)
|
129
|
+
end
|
130
|
+
|
131
|
+
context 'and the Movable has no parent' do
|
132
|
+
before(:each) do
|
133
|
+
allow(subject).to receive(:parent).and_return(nil)
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'returns itself' do
|
137
|
+
expect(subject.move_to(new_parent, :test)).to eq(subject)
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'calls #parent' do
|
141
|
+
expect(subject).to receive(:parent)
|
142
|
+
subject.move_to(new_parent, :test)
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'calls #add on the new parent with the ID and Movable' do
|
146
|
+
expect(new_parent).to receive(:add).with(:test_id, subject)
|
147
|
+
|
148
|
+
subject.move_to(new_parent, :test_id)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
context 'and the Movable has a parent that refuses to remove it' do
|
153
|
+
before(:each) do
|
154
|
+
allow(subject).to receive(:parent).and_return(old_parent)
|
155
|
+
allow(old_parent).to receive(:remove).and_return(nil)
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'returns itself' do
|
159
|
+
expect(subject.move_to(new_parent, :test)).to eq(subject)
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'calls #parent' do
|
163
|
+
expect(subject).to receive(:parent)
|
164
|
+
subject.move_to(new_parent, :test)
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'calls #remove on the old parent with the Movable' do
|
168
|
+
expect(old_parent).to receive(:remove).once.with(subject)
|
169
|
+
subject.move_to(new_parent, :test)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
context 'and the Movable has a parent that allows it to be removed' do
|
174
|
+
before(:each) do
|
175
|
+
allow(subject).to receive(:parent).and_return(old_parent)
|
176
|
+
allow(old_parent).to receive(:remove).and_return(subject)
|
177
|
+
allow(new_parent).to receive(:add)
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'returns itself' do
|
181
|
+
expect(subject.move_to(new_parent, :test)).to eq(subject)
|
182
|
+
end
|
183
|
+
|
184
|
+
it 'calls #parent' do
|
185
|
+
expect(subject).to receive(:parent)
|
186
|
+
subject.move_to(new_parent, :test)
|
187
|
+
end
|
188
|
+
|
189
|
+
it 'calls #remove on the old parent with the Movable' do
|
190
|
+
expect(old_parent).to receive(:remove).once.with(subject)
|
191
|
+
subject.move_to(new_parent, :test)
|
192
|
+
end
|
193
|
+
|
194
|
+
it 'calls #add on the new parent with the ID and Movable' do
|
195
|
+
expect(new_parent).to receive(:add).once.with(:test, subject)
|
196
|
+
subject.move_to(new_parent, :test)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'compo'
|
3
|
+
|
4
|
+
describe Compo::NullComposite do
|
5
|
+
let(:child1) { double(:child1) }
|
6
|
+
let(:child2) { double(:child2) }
|
7
|
+
let(:child3) { double(:child3) }
|
8
|
+
|
9
|
+
describe '#add' do
|
10
|
+
it 'always returns nil' do
|
11
|
+
expect(subject.add(1, child1)).to be_nil
|
12
|
+
expect(subject.add(:a, child2)).to be_nil
|
13
|
+
expect(subject.add(nil, child3)).to be_nil
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'does not change the result of #children' do
|
17
|
+
expect(subject.children).to eq({})
|
18
|
+
|
19
|
+
subject.add(1, child1)
|
20
|
+
expect(subject.children).to eq({})
|
21
|
+
|
22
|
+
subject.add(:a, child2)
|
23
|
+
expect(subject.children).to eq({})
|
24
|
+
|
25
|
+
subject.add(:a, child3)
|
26
|
+
expect(subject.children).to eq({})
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#remove' do
|
31
|
+
specify { expect(subject.remove(child1)).to eq(nil) }
|
32
|
+
|
33
|
+
it 'does not change the result of #children' do
|
34
|
+
expect(subject.children).to eq({})
|
35
|
+
|
36
|
+
subject.remove(child1)
|
37
|
+
expect(subject.children).to eq({})
|
38
|
+
|
39
|
+
subject.remove(child2)
|
40
|
+
expect(subject.children).to eq({})
|
41
|
+
|
42
|
+
subject.remove(child3)
|
43
|
+
expect(subject.children).to eq({})
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#remove_id' do
|
48
|
+
specify { expect(subject.remove_id(:a)).to eq(nil) }
|
49
|
+
|
50
|
+
it 'does not change the result of #children' do
|
51
|
+
expect(subject.children).to eq({})
|
52
|
+
|
53
|
+
subject.remove_id(0)
|
54
|
+
expect(subject.children).to eq({})
|
55
|
+
|
56
|
+
subject.remove_id(:a)
|
57
|
+
expect(subject.children).to eq({})
|
58
|
+
|
59
|
+
subject.remove_id(nil)
|
60
|
+
expect(subject.children).to eq({})
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe '#children' do
|
65
|
+
specify { expect(subject.children).to eq({}) }
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'compo'
|
3
|
+
|
4
|
+
# Mock implementation of a ParentTracker
|
5
|
+
class MockParentTracker
|
6
|
+
include Compo::ParentTracker
|
7
|
+
|
8
|
+
def initialize(parent, id_function)
|
9
|
+
@parent = parent
|
10
|
+
@id_function = id_function
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe MockParentTracker do
|
15
|
+
subject { MockParentTracker.new(parent, id_function) }
|
16
|
+
let(:parent) { double(:parent) }
|
17
|
+
let(:id_function) { double(:id_function) }
|
18
|
+
|
19
|
+
describe '#parent' do
|
20
|
+
it 'returns the current parent' do
|
21
|
+
expect(subject.parent).to eq(parent)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#id' do
|
26
|
+
it 'calls the current ID function and returns its result' do
|
27
|
+
allow(id_function).to receive(:call).and_return(:id)
|
28
|
+
expect(id_function).to receive(:call).once.with(no_args)
|
29
|
+
|
30
|
+
expect(subject.id).to eq(:id)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#update_parent' do
|
35
|
+
let(:new_parent) { double(:new_parent) }
|
36
|
+
let(:new_id_function) { double(:new_id_function) }
|
37
|
+
|
38
|
+
it 'sets the parent to the new value' do
|
39
|
+
subject.update_parent(new_parent, new_id_function)
|
40
|
+
expect(subject.parent).to eq(new_parent)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'sets the ID function to the new ID function' do
|
44
|
+
allow(new_id_function).to receive(:call).and_return(:new_id)
|
45
|
+
expect(new_id_function).to receive(:call).once
|
46
|
+
|
47
|
+
subject.update_parent(new_parent, new_id_function)
|
48
|
+
expect(subject.id).to eq(:new_id)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '#remove_parent' do
|
53
|
+
it 'sets the parent to nil' do
|
54
|
+
subject.remove_parent
|
55
|
+
expect(subject.parent).to be_nil
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'sets the ID function to one returning nil' do
|
59
|
+
subject.remove_parent
|
60
|
+
expect(subject.id).to be_nil
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,192 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: compo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Matt Windsor
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-12-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: backports
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.3'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: fuubar
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: simplecov
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: yard
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: yardstick
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
description: "\n Compo provides mixins and classes that assist in implementing
|
126
|
+
a variant of\n the Composite design pattern, in which each child has an ID that
|
127
|
+
uniquely\n identifies it inside the parent's child set.\n "
|
128
|
+
email:
|
129
|
+
- matt.windsor@ury.org.uk
|
130
|
+
executables: []
|
131
|
+
extensions: []
|
132
|
+
extra_rdoc_files: []
|
133
|
+
files:
|
134
|
+
- .gitignore
|
135
|
+
- .rspec
|
136
|
+
- CHANGELOG
|
137
|
+
- Gemfile
|
138
|
+
- LICENSE.txt
|
139
|
+
- README.md
|
140
|
+
- Rakefile
|
141
|
+
- compo.gemspec
|
142
|
+
- lib/compo.rb
|
143
|
+
- lib/compo/array_composite.rb
|
144
|
+
- lib/compo/composite.rb
|
145
|
+
- lib/compo/hash_composite.rb
|
146
|
+
- lib/compo/leaf.rb
|
147
|
+
- lib/compo/movable.rb
|
148
|
+
- lib/compo/null_composite.rb
|
149
|
+
- lib/compo/parent_tracker.rb
|
150
|
+
- lib/compo/version.rb
|
151
|
+
- spec/array_composite_spec.rb
|
152
|
+
- spec/composite_spec.rb
|
153
|
+
- spec/hash_composite_spec.rb
|
154
|
+
- spec/leaf_spec.rb
|
155
|
+
- spec/movable_spec.rb
|
156
|
+
- spec/null_composite_spec.rb
|
157
|
+
- spec/parent_tracker_spec.rb
|
158
|
+
- spec/spec_helper.rb
|
159
|
+
homepage: http://github.com/CaptainHayashi/compo
|
160
|
+
licenses:
|
161
|
+
- MIT
|
162
|
+
metadata: {}
|
163
|
+
post_install_message:
|
164
|
+
rdoc_options: []
|
165
|
+
require_paths:
|
166
|
+
- lib
|
167
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
168
|
+
requirements:
|
169
|
+
- - '>='
|
170
|
+
- !ruby/object:Gem::Version
|
171
|
+
version: '0'
|
172
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
173
|
+
requirements:
|
174
|
+
- - '>='
|
175
|
+
- !ruby/object:Gem::Version
|
176
|
+
version: '0'
|
177
|
+
requirements: []
|
178
|
+
rubyforge_project:
|
179
|
+
rubygems_version: 2.0.14
|
180
|
+
signing_key:
|
181
|
+
specification_version: 4
|
182
|
+
summary: Composite pattern style mixins with IDs
|
183
|
+
test_files:
|
184
|
+
- spec/array_composite_spec.rb
|
185
|
+
- spec/composite_spec.rb
|
186
|
+
- spec/hash_composite_spec.rb
|
187
|
+
- spec/leaf_spec.rb
|
188
|
+
- spec/movable_spec.rb
|
189
|
+
- spec/null_composite_spec.rb
|
190
|
+
- spec/parent_tracker_spec.rb
|
191
|
+
- spec/spec_helper.rb
|
192
|
+
has_rdoc:
|