compo 0.4.0 → 0.5.0

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: 9a7465849db65d98eec1007ce000a7a75fa78309
4
- data.tar.gz: 6472acc91b29bda5ba2c3886a0a50a88f28f8c74
3
+ metadata.gz: b36ac99cbd26e363126ccaa0e1a2dd20ba9d4b10
4
+ data.tar.gz: 3a026f05f3e59917727599e3cc83b2a7888e9bb8
5
5
  SHA512:
6
- metadata.gz: 84cfa4992537c356070d0a2885cff6bfd3e6e39050bdb6986ac413d1c6920dc05316b945e5f2e1f7fe79fc044d318d602c3a6a9befc404ca9814b622a238737e
7
- data.tar.gz: edd697d7696e8e96783d4e02bfc37852df79abbacab5b992c1c6b8d0c95002763416caaf9e2bc2e6f51f1c98960612783cc182339e6b0956ce6ef95873cad675
6
+ metadata.gz: 457dec32c46dabfa7e03b79545930df61cd9b9777dab0f8d8c436ec4dc425e091ab04b85af9810302fe9725809edab277c4f90a032676acc30fd3711d8c9032f
7
+ data.tar.gz: 18fd9981c0e31255bce927311b4c624ec2c08adbc27c9de043353228267230e3f896cfd6ac068ff28b2859dba8ca56a1869847cc57b8d65996aada33bed5af01
data/.rspec CHANGED
@@ -1,2 +1 @@
1
- --format Fuubar
2
1
  --color
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.2
data/CHANGELOG CHANGED
@@ -1,3 +1,14 @@
1
+ 0.5.0 (2014-07-10) ‘Brimble’
2
+ - Implement a root finder, which has the ability to enumerate the entire path
3
+ from a parent-tracking composite object up to its root.
4
+ - Implement new method #on_node, which executes a block if, and only if, the
5
+ object is an actual composite node (not a Parentless, etc.).
6
+ - Implement new method #root?, which returns true if, and only if, the
7
+ object does not have a valid parent (its parent ignores #on_node).
8
+ - Refactor UrlReferenceable such that URLs are calculated via the root finder.
9
+ This is now an iterative algorithm and shouldn't exhaust the stack on large
10
+ composites.
11
+ - (BACKWARDS INCOMPATIBILITY) Remove #child_url, as it is no longer needed.
1
12
  0.4.0 (2014-05-22) ‘De Vorzon’
2
13
  Big release with quite a few changes:
3
14
  - (BACKWARDS INCOMPATIBILITY) Reorganise classes into submodules. This has
data/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # Compo
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/compo.svg)](http://badge.fury.io/rb/compo)
4
+ [![Build Status](https://travis-ci.org/CaptainHayashi/compo.svg)](https://travis-ci.org/CaptainHayashi/compo)
5
+
3
6
  **Compo** is a library providing mixins and base classes for setting up
4
7
  composite objects.
5
8
 
data/compo.gemspec CHANGED
@@ -9,11 +9,11 @@ Gem::Specification.new do |spec|
9
9
  spec.version = Compo::VERSION
10
10
  spec.authors = ['Matt Windsor']
11
11
  spec.email = ['matt.windsor@ury.org.uk']
12
- spec.description = %q(
12
+ spec.description = <<-DESC
13
13
  Compo provides mixins and classes that assist in implementing a variant of
14
14
  the Composite design pattern, in which each child has an ID that uniquely
15
15
  identifies it inside the parent's child set.
16
- )
16
+ DESC
17
17
  spec.summary = 'Composite pattern style mixins with IDs'
18
18
  spec.homepage = 'http://github.com/CaptainHayashi/compo'
19
19
  spec.license = 'MIT'
@@ -25,9 +25,8 @@ Gem::Specification.new do |spec|
25
25
 
26
26
  spec.add_development_dependency 'backports'
27
27
  spec.add_development_dependency 'bundler', '~> 1.6'
28
- spec.add_development_dependency 'fuubar'
29
28
  spec.add_development_dependency 'rake'
30
- spec.add_development_dependency 'rspec'
29
+ spec.add_development_dependency 'rspec', '~> 3'
31
30
  spec.add_development_dependency 'simplecov'
32
31
  spec.add_development_dependency 'yard'
33
32
  spec.add_development_dependency 'yardstick'
@@ -123,6 +123,22 @@ module Compo
123
123
 
124
124
  def_delegator :children, :each
125
125
 
126
+ # Performs an action on this node, if it is an actual Composite node
127
+ #
128
+ # By default, this does indeed run the block provided, and returns the
129
+ # block's result. Composites that do not represent proper nodes (for
130
+ # example, Parentless) may override this to ignore the block and return
131
+ # nil.
132
+ #
133
+ # @api public
134
+ # @example Performs an action on this Parentless.
135
+ # parentless.on_node { |n| 3 }
136
+ # #=> 3
137
+ # @return [false]
138
+ def on_node
139
+ yield self
140
+ end
141
+
126
142
  protected
127
143
 
128
144
  # Assigns this object to a child as its parent
@@ -71,21 +71,6 @@ module Compo
71
71
  ''
72
72
  end
73
73
 
74
- # Given the ID of a child in this Parentless, returns that child's URL
75
- #
76
- # This is always the empty string. This is so that children of orphan
77
- # objects have URLs starting with /their_id.
78
- #
79
- # @api public
80
- # @example Gets the URL of the child of a Parentless.
81
- # parentless.child_url(:child_id)
82
- # #=> ''
83
- #
84
- # @return [Hash] The empty string.
85
- def child_url(_)
86
- ''
87
- end
88
-
89
74
  # Returns the parent of this Parentless
90
75
  #
91
76
  # This is always the same Parentless, for convenience's sake.
@@ -100,6 +85,20 @@ module Compo
100
85
  self
101
86
  end
102
87
 
88
+ # Performs an action on this node, if it is an actual Composite node
89
+ #
90
+ # A Parentless is not, and thus this method returns nil and ignores
91
+ # any block present.
92
+ #
93
+ # @api public
94
+ # @example (Doesn't) perform an action on this Parentless.
95
+ # parentless.on_node { |n| 3 }
96
+ # #=> nil
97
+ # @return [nil]
98
+ def on_node
99
+ nil
100
+ end
101
+
103
102
  protected
104
103
 
105
104
  # 'Adds' a child to this Parentless
@@ -0,0 +1,77 @@
1
+ module Compo
2
+ module Finders
3
+ # A method object for finding the root of an item in a composite tree
4
+ #
5
+ # The RootFinder can be used as an Enumerable, where the enumerated items
6
+ # are the path of nodes from the composite to its root, inclusive.
7
+ #
8
+ # Root finders are *not* thread-safe.
9
+ class Root
10
+ include Enumerable
11
+
12
+ # Initialises a root finder
13
+ #
14
+ # @api public
15
+ # @example Initialises a RootFinder
16
+ # RootFinder.new(composite)
17
+ #
18
+ # @param leaf [Composite] A composite object whose root is to be found.
19
+ def initialize(leaf)
20
+ @leaf = leaf
21
+ end
22
+
23
+ # Finds the root of a composite object
24
+ #
25
+ # @api public
26
+ # @example Finds the root of an object
27
+ # RootFinder.find(composite) { |root| p root }
28
+ #
29
+ # @param (see #initialize)
30
+ #
31
+ # @yieldparam (see #run)
32
+ #
33
+ # @return [Object] The return value of the block.
34
+ def self.find(*args, &block)
35
+ new(*args).run(&block)
36
+ end
37
+
38
+ # Attempts to find the root of this RootFinder's composite object
39
+ #
40
+ # When the resource is found, it will be yielded to the attached block.
41
+ #
42
+ # @api public
43
+ # @example Runs an RootFinder, returning the root unchanged.
44
+ # finder.run { |root| root }
45
+ # #=> root
46
+ #
47
+ # @yieldparam resource [Object] The resource found.
48
+ #
49
+ # @return [Object] The return value of the block.
50
+ def run
51
+ each { |node| yield node if node.root? }
52
+ end
53
+
54
+ # Performs an action on each node in the path to the root
55
+ #
56
+ # This includes both the root and the object whose root is sought, and
57
+ # runs from the latter to the former.
58
+ #
59
+ # @api public
60
+ # @example Prints each item from the object to the root.
61
+ # finder.each { |item| puts item }
62
+ #
63
+ # @yieldparam resource [Object] The resource found.
64
+ #
65
+ # @return [void]
66
+ def each
67
+ node = @leaf
68
+ done = false
69
+ until done
70
+ yield node
71
+ done = node.root?
72
+ node = node.parent
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
data/lib/compo/finders.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require 'compo/finders/root'
1
2
  require 'compo/finders/url'
2
3
 
3
4
  module Compo
@@ -29,6 +29,21 @@ module Compo
29
29
  Compo::Composites::Parentless.for(self)
30
30
  end
31
31
 
32
+ # Gets whether this ParentTracker is the root of its composite tree
33
+ #
34
+ # This is equivalent to the ParentTracker having no parent.
35
+ #
36
+ # @api public
37
+ # @example Checks if a ParentTracker with no parent is a root.
38
+ # orphan.root?
39
+ # #=> true
40
+ # @example Checks if a ParentTracker with a parent is a root.
41
+ # parented.root?
42
+ # #=> false
43
+ def root?
44
+ parent.on_node { |p| p }.nil?
45
+ end
46
+
32
47
  # Gets this object's current ID
33
48
  #
34
49
  # @api public
@@ -1,3 +1,5 @@
1
+ require 'compo/finders/root'
2
+
1
3
  module Compo
2
4
  module Mixins
3
5
  # Adds ID-based 'URL's to Compo classes
@@ -26,30 +28,13 @@ module Compo
26
28
  # #=> ''
27
29
  # @example Gets the URL of an object with a parent.
28
30
  # leaf.url
29
- # #=> 'grandparent_id/parent_id/id'
31
+ # #=> '/grandparent_id/parent_id/id'
30
32
  #
31
33
  # @return [String] The URL of this object.
32
34
  def url
33
- parent.child_url(id)
34
- end
35
-
36
- # Returns the URL of a child of this object, with the given ID
37
- #
38
- # This defaults to joining the ID to this object's URL with a slash.
39
- #
40
- # @api public
41
- # @example Gets the URL of the child of an object without a parent.
42
- # orphan.child_url(:id)
43
- # #=> '/id'
44
- # @example Gets the URL of the child of an object with a parent.
45
- # leaf.child_url(:id)
46
- # #=> 'grandparent_id/parent_id/id'
47
- #
48
- # @param child_id [Object] The ID of the child whose URL is sought.
49
- #
50
- # @return [String] The URL of the child with the given ID.
51
- def child_url(child_id)
52
- [url, child_id].join('/')
35
+ Compo::Finders::Root.new(self).reverse_each.map do |item|
36
+ item.root? ? '' : item.id
37
+ end.join('/')
53
38
  end
54
39
 
55
40
  # Returns the URL of this object's parent
@@ -57,10 +42,10 @@ module Compo
57
42
  # @api public
58
43
  # @example Gets the parent URL of an object with no parent.
59
44
  # orphan.parent_url
60
- # #=> nil
45
+ # #=> ''
61
46
  # @example Gets the URL of an object with a parent.
62
47
  # leaf.parent_url
63
- # #=> 'grandparent_id/parent_id'
48
+ # #=> '/grandparent_id/parent_id'
64
49
  #
65
50
  # @return [String] The URL of this object's parent, or nil if there is no
66
51
  # parent.
data/lib/compo/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  # The current gem version. See CHANGELOG for information.
2
2
  module Compo
3
- VERSION = '0.4.0'
3
+ VERSION = '0.5.0'
4
4
  end
@@ -3,7 +3,7 @@ require 'compo'
3
3
  require 'array_composite_shared_examples'
4
4
  require 'branch_shared_examples'
5
5
 
6
- describe Compo::Branches::Array do
6
+ RSpec.describe Compo::Branches::Array do
7
7
  it_behaves_like 'a branch with children' do
8
8
  let(:initial_ids) { [0, 1] }
9
9
  end
@@ -1,113 +1,120 @@
1
1
  require 'compo'
2
2
  require 'composite_shared_examples'
3
3
 
4
- shared_examples 'an array composite' do
4
+ RSpec.shared_examples 'an array composite' do
5
5
  it_behaves_like 'a composite'
6
6
 
7
- let(:child1) { double(:child1) }
8
- let(:child2) { double(:child2) }
9
- let(:child3) { double(:child3) }
7
+ # Children
8
+ let(:c1) { double(:c1) }
9
+ let(:c2) { double(:c2) }
10
+ let(:c3) { double(:c3) }
10
11
 
11
12
  before(:each) do
12
- allow(child1).to receive(:update_parent)
13
- allow(child2).to receive(:update_parent)
14
- allow(child3).to receive(:update_parent)
13
+ allow(c1).to receive(:update_parent)
14
+ allow(c2).to receive(:update_parent)
15
+ allow(c3).to receive(:update_parent)
15
16
  end
16
17
 
17
18
  describe '#add' do
18
19
  context 'when the ID is not Numeric' do
19
- specify { expect(subject.add(:mr_flibble, child1)).to be_nil }
20
+ specify { expect(subject.add(:mr_flibble, c1)).to be_nil }
20
21
 
21
22
  it 'does not add to the list of children' do
22
- subject.add(:rimmer, child1)
23
- expect(subject.children).to eq({})
23
+ expect { subject.add(:rimmer, c1) }.to_not change { subject.children }
24
+ .from({})
25
+
26
+ subject.add(0, c1)
24
27
 
25
- subject.add(0, child1)
26
- subject.add(:lister, child2)
27
- expect(subject.children).to eq(0 => child1)
28
+ expect { subject.add(:lister, c2) }.to_not change { subject.children }
29
+ .from(0 => c1)
28
30
 
29
- subject.add(1, child2)
30
- subject.add(:cat, child3)
31
- expect(subject.children).to eq(0 => child1, 1 => child2)
31
+ subject.add(1, c2)
32
+
33
+ expect { subject.add(:cat, c3) }.to_not change { subject.children }
34
+ .from(0 => c1, 1 => c2)
32
35
  end
33
36
  end
34
37
  context 'when the ID is Numeric' do
35
38
  context 'and is equal to the number of children' do
36
39
  it 'returns the child' do
37
- expect(subject.add(0, child1)).to eq(child1)
38
- expect(subject.add(1, child2)).to eq(child2)
39
- expect(subject.add(2, child3)).to eq(child3)
40
+ expect(subject.add(0, c1)).to eq(c1)
41
+ expect(subject.add(1, c2)).to eq(c2)
42
+ expect(subject.add(2, c3)).to eq(c3)
40
43
  end
41
44
 
42
45
  it 'adds to the end of the list of children' do
43
46
  expect(subject.children).to eq({})
44
47
 
45
- subject.add(0, child1)
46
- expect(subject.children).to eq(0 => child1)
47
-
48
- subject.add(1, child2)
49
- expect(subject.children).to eq(0 => child1, 1 => child2)
50
-
51
- subject.add(2, child3)
52
- expect(subject.children).to eq(0 => child1, 1 => child2, 2 => child3)
48
+ expect { subject.add(0, c1) }.to change { subject.children }
49
+ .from({})
50
+ .to(0 => c1)
51
+ expect { subject.add(1, c2) }.to change { subject.children }
52
+ .from(0 => c1)
53
+ .to(0 => c1, 1 => c2)
54
+ expect { subject.add(2, c3) }.to change { subject.children }
55
+ .from(0 => c1, 1 => c2)
56
+ .to(0 => c1, 1 => c2, 2 => c3)
53
57
  end
54
58
 
55
59
  it 'calls #update_parent on the child with itself and an ID proc' do
56
- expect(child1).to receive(:update_parent) do |parent, proc|
57
- expect(parent).to eq(subject)
58
- expect(proc.call).to eq(0)
59
- end
60
- subject.add(0, child1)
60
+ expect(c1).to receive(:update_parent).with(
61
+ subject,
62
+ an_object_satisfying { |proc| proc.call == 0 }
63
+ )
64
+ subject.add(0, c1)
61
65
  end
62
66
  end
63
67
 
64
68
  context 'and is greater than the number of children' do
65
69
  it 'returns nil' do
66
- expect(subject.add(1, child1)).to be_nil
67
- subject.add(0, child1)
68
- expect(subject.add(2, child2)).to be_nil
69
- subject.add(1, child2)
70
- expect(subject.add(3, child3)).to be_nil
70
+ expect(subject.add(1, c1)).to be_nil
71
+ subject.add(0, c1)
72
+ expect(subject.add(2, c2)).to be_nil
73
+ subject.add(1, c2)
74
+ expect(subject.add(3, c3)).to be_nil
71
75
  end
72
76
 
73
77
  it 'does not add to the list of children' do
74
- subject.add(1, child1)
75
- expect(subject.children).to eq({})
78
+ expect { subject.add(1, c1) }.to_not change { subject.children }
79
+ .from({})
76
80
 
77
- subject.add(0, child1)
78
- subject.add(2, child2)
79
- expect(subject.children).to eq(0 => child1)
81
+ subject.add(0, c1)
82
+ expect { subject.add(2, c2) }.to_not change { subject.children }
83
+ .from(0 => c1)
80
84
 
81
- subject.add(1, child2)
82
- subject.add(3, child3)
83
- expect(subject.children).to eq(0 => child1, 1 => child2)
85
+ subject.add(1, c2)
86
+ expect { subject.add(3, c2) }.to_not change { subject.children }
87
+ .from(0 => c1, 1 => c2)
84
88
  end
85
89
  end
86
90
 
87
91
  context 'and is less than the number of children' do
88
92
  it 'returns the child' do
89
- subject.add(0, child1)
90
- expect(subject.add(0, child2)).to eq(child2)
91
- expect(subject.add(1, child3)).to eq(child3)
93
+ subject.add(0, c1)
94
+ expect(subject.add(0, c2)).to eq(c2)
95
+ expect(subject.add(1, c3)).to eq(c3)
92
96
  end
93
97
 
94
98
  it 'adds to the list of children at the correct position' do
95
99
  expect(subject.children).to eq({})
96
- subject.add(0, child1)
97
- expect(subject.children).to eq(0 => child1)
98
- subject.add(0, child2)
99
- expect(subject.children).to eq(0 => child2, 1 => child1)
100
- subject.add(1, child3)
101
- expect(subject.children).to eq(0 => child2, 1 => child3, 2 => child1)
100
+ expect { subject.add(0, c1) }.to change { subject.children }
101
+ .from({})
102
+ .to(0 => c1)
103
+ expect { subject.add(0, c2) }.to change { subject.children }
104
+ .from(0 => c1)
105
+ .to(0 => c2, 1 => c1)
106
+ expect { subject.add(1, c3) }.to change { subject.children }
107
+ .from(0 => c2, 1 => c1)
108
+ .to(0 => c2, 1 => c3, 2 => c1)
102
109
  end
103
110
 
104
111
  it 'calls #update_parent on the child with itself and an ID proc' do
105
- expect(child1).to receive(:update_parent) do |parent, proc|
112
+ expect(c1).to receive(:update_parent) do |parent, proc|
106
113
  expect(parent).to eq(subject)
107
114
  expect(proc.call).to eq(0)
108
115
  end
109
- subject.add(0, child2)
110
- subject.add(0, child1)
116
+ subject.add(0, c2)
117
+ subject.add(0, c1)
111
118
  end
112
119
  end
113
120
  end
@@ -115,80 +122,80 @@ shared_examples 'an array composite' do
115
122
 
116
123
  describe '#remove' do
117
124
  context 'when the child exists in the list' do
118
- before(:each) { subject.add(0, child1) }
125
+ before(:each) { subject.add(0, c1) }
119
126
 
120
127
  it 'returns the child' do
121
- expect(subject.remove(child1)).to eq(child1)
128
+ expect(subject.remove(c1)).to eq(c1)
122
129
  end
123
130
 
124
131
  it 'calls #update_parent on the child with a Parentless' do
125
- expect(child1).to receive(:update_parent).once do |parent, _|
132
+ expect(c1).to receive(:update_parent).once do |parent, _|
126
133
  expect(parent).to be_a(Compo::Composites::Parentless)
127
134
  end
128
- subject.remove(child1)
135
+ subject.remove(c1)
129
136
  end
130
137
 
131
138
  it 'calls #update_parent on the child with a nil-returning ID proc' do
132
- expect(child1).to receive(:update_parent).once do |_, idp|
139
+ expect(c1).to receive(:update_parent).once do |_, idp|
133
140
  expect(idp.call).to be_nil
134
141
  end
135
- subject.remove(child1)
142
+ subject.remove(c1)
136
143
  end
137
144
 
138
145
  it 'moves succeeding IDs down by one' do
139
- subject.add(1, child2)
140
- subject.add(2, child3)
141
- expect(subject.children).to eq(0 => child1, 1 => child2, 2 => child3)
142
- subject.remove(child2)
143
- expect(subject.children).to eq(0 => child1, 1 => child3)
146
+ subject.add(1, c2)
147
+ subject.add(2, c3)
148
+
149
+ expect { subject.remove(c2) }.to change { subject.children }
150
+ .from(0 => c1, 1 => c2, 2 => c3)
151
+ .to(0 => c1, 1 => c3)
144
152
  end
145
153
  end
146
154
 
147
155
  context 'when the child does not exist in the list' do
148
- specify { expect(subject.remove(child1)).to be_nil }
156
+ specify { expect(subject.remove(c1)).to be_nil }
149
157
 
150
158
  it 'does not change the children' do
151
159
  expect(subject.children).to eq({})
152
- subject.remove(child1)
153
- expect(subject.children).to eq({})
160
+ expect { subject.remove(c1) }.to_not change { subject.children }
161
+ .from({})
154
162
 
155
- subject.add(0, child1)
156
- subject.add(1, child2)
157
- expect(subject.children).to eq(0 => child1, 1 => child2)
158
- subject.remove(child3)
159
- expect(subject.children).to eq(0 => child1, 1 => child2)
163
+ subject.add(0, c1)
164
+ subject.add(1, c2)
165
+ expect { subject.remove(c3) }.to_not change { subject.children }
166
+ .from eq(0 => c1, 1 => c2)
160
167
  end
161
168
  end
162
169
  end
163
170
 
164
171
  describe '#remove_id' do
165
172
  context 'when the ID exists' do
166
- before(:each) { subject.add(0, child1) }
173
+ before(:each) { subject.add(0, c1) }
167
174
 
168
175
  it 'returns the child' do
169
- expect(subject.remove_id(0)).to eq(child1)
176
+ expect(subject.remove_id(0)).to eq(c1)
170
177
  end
171
178
 
172
179
  it 'calls #update_parent on the child with a Parentless' do
173
- expect(child1).to receive(:update_parent).once do |parent, _|
180
+ expect(c1).to receive(:update_parent).once do |parent, _|
174
181
  expect(parent).to be_a(Compo::Composites::Parentless)
175
182
  end
176
183
  subject.remove_id(0)
177
184
  end
178
185
 
179
186
  it 'calls #update_parent on the child with a nil-returning ID proc' do
180
- expect(child1).to receive(:update_parent).once do |_, idp|
187
+ expect(c1).to receive(:update_parent).once do |_, idp|
181
188
  expect(idp.call).to be_nil
182
189
  end
183
190
  subject.remove_id(0)
184
191
  end
185
192
 
186
193
  it 'moves succeeding IDs down by one' do
187
- subject.add(1, child2)
188
- subject.add(2, child3)
189
- expect(subject.children).to eq(0 => child1, 1 => child2, 2 => child3)
190
- subject.remove_id(1)
191
- expect(subject.children).to eq(0 => child1, 1 => child3)
194
+ subject.add(1, c2)
195
+ subject.add(2, c3)
196
+ expect { subject.remove_id(1) }.to change { subject.children }
197
+ .from(0 => c1, 1 => c2, 2 => c3)
198
+ .to(0 => c1, 1 => c3)
192
199
  end
193
200
  end
194
201
 
@@ -196,15 +203,13 @@ shared_examples 'an array composite' do
196
203
  specify { expect(subject.remove_id(0)).to be_nil }
197
204
 
198
205
  it 'does not change the children' do
199
- expect(subject.children).to eq({})
200
- subject.remove_id(0)
201
- expect(subject.children).to eq({})
206
+ expect { subject.remove_id(0) }.to_not change { subject.children }
207
+ .from({})
202
208
 
203
- subject.add(0, child1)
204
- subject.add(1, child2)
205
- expect(subject.children).to eq(0 => child1, 1 => child2)
206
- subject.remove_id(2)
207
- expect(subject.children).to eq(0 => child1, 1 => child2)
209
+ subject.add(0, c1)
210
+ subject.add(1, c2)
211
+ expect { subject.remove_id(2) }.to_not change { subject.children }
212
+ .from(0 => c1, 1 => c2)
208
213
  end
209
214
  end
210
215
  end
@@ -220,20 +225,20 @@ shared_examples 'an array composite' do
220
225
  it 'returns a hash mapping their current indices to themselves' do
221
226
  expect(subject.children).to eq({})
222
227
 
223
- subject.add(0, child1)
224
- expect(subject.children).to eq(0 => child1)
228
+ subject.add(0, c1)
229
+ expect(subject.children).to eq(0 => c1)
225
230
 
226
- subject.add(1, child2)
227
- expect(subject.children).to eq(0 => child1, 1 => child2)
231
+ subject.add(1, c2)
232
+ expect(subject.children).to eq(0 => c1, 1 => c2)
228
233
 
229
- subject.add(2, child3)
230
- expect(subject.children).to eq(0 => child1, 1 => child2, 2 => child3)
234
+ subject.add(2, c3)
235
+ expect(subject.children).to eq(0 => c1, 1 => c2, 2 => c3)
231
236
 
232
- subject.remove(child2)
233
- expect(subject.children).to eq(0 => child1, 1 => child3)
237
+ subject.remove(c2)
238
+ expect(subject.children).to eq(0 => c1, 1 => c3)
234
239
 
235
- subject.add(0, child2)
236
- expect(subject.children).to eq(0 => child2, 1 => child1, 2 => child3)
240
+ subject.add(0, c2)
241
+ expect(subject.children).to eq(0 => c2, 1 => c1, 2 => c3)
237
242
  end
238
243
  end
239
244
  end