rambling-trie 1.0.2 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +5 -5
  2. data/Gemfile +6 -3
  3. data/Guardfile +3 -1
  4. data/README.md +30 -12
  5. data/Rakefile +8 -0
  6. data/lib/rambling-trie.rb +2 -0
  7. data/lib/rambling/trie.rb +48 -26
  8. data/lib/rambling/trie/comparable.rb +6 -3
  9. data/lib/rambling/trie/compressible.rb +16 -0
  10. data/lib/rambling/trie/compressor.rb +39 -24
  11. data/lib/rambling/trie/configuration.rb +3 -1
  12. data/lib/rambling/trie/configuration/properties.rb +18 -9
  13. data/lib/rambling/trie/configuration/provider_collection.rb +38 -17
  14. data/lib/rambling/trie/container.rb +123 -36
  15. data/lib/rambling/trie/enumerable.rb +6 -4
  16. data/lib/rambling/trie/inspectable.rb +2 -0
  17. data/lib/rambling/trie/invalid_operation.rb +3 -1
  18. data/lib/rambling/trie/nodes.rb +13 -0
  19. data/lib/rambling/trie/nodes/compressed.rb +98 -0
  20. data/lib/rambling/trie/nodes/missing.rb +12 -0
  21. data/lib/rambling/trie/nodes/node.rb +183 -0
  22. data/lib/rambling/trie/nodes/raw.rb +82 -0
  23. data/lib/rambling/trie/readers.rb +3 -1
  24. data/lib/rambling/trie/readers/plain_text.rb +3 -11
  25. data/lib/rambling/trie/serializers.rb +3 -1
  26. data/lib/rambling/trie/serializers/file.rb +2 -0
  27. data/lib/rambling/trie/serializers/marshal.rb +15 -5
  28. data/lib/rambling/trie/serializers/yaml.rb +21 -5
  29. data/lib/rambling/trie/serializers/zip.rb +15 -8
  30. data/lib/rambling/trie/stringifyable.rb +8 -2
  31. data/lib/rambling/trie/version.rb +3 -1
  32. data/rambling-trie.gemspec +21 -10
  33. data/spec/assets/test_words.es_DO.txt +1 -0
  34. data/spec/integration/rambling/trie_spec.rb +44 -35
  35. data/spec/lib/rambling/trie/comparable_spec.rb +8 -15
  36. data/spec/lib/rambling/trie/compressor_spec.rb +90 -13
  37. data/spec/lib/rambling/trie/configuration/properties_spec.rb +21 -13
  38. data/spec/lib/rambling/trie/configuration/provider_collection_spec.rb +18 -34
  39. data/spec/lib/rambling/trie/container_spec.rb +183 -217
  40. data/spec/lib/rambling/trie/enumerable_spec.rb +14 -9
  41. data/spec/lib/rambling/trie/inspectable_spec.rb +36 -11
  42. data/spec/lib/rambling/trie/nodes/compressed_spec.rb +37 -0
  43. data/spec/lib/rambling/trie/nodes/node_spec.rb +9 -0
  44. data/spec/lib/rambling/trie/nodes/raw_spec.rb +179 -0
  45. data/spec/lib/rambling/trie/readers/plain_text_spec.rb +3 -1
  46. data/spec/lib/rambling/trie/serializers/file_spec.rb +6 -4
  47. data/spec/lib/rambling/trie/serializers/marshal_spec.rb +5 -7
  48. data/spec/lib/rambling/trie/serializers/yaml_spec.rb +5 -7
  49. data/spec/lib/rambling/trie/serializers/zip_spec.rb +18 -20
  50. data/spec/lib/rambling/trie/stringifyable_spec.rb +14 -11
  51. data/spec/lib/rambling/trie_spec.rb +18 -11
  52. data/spec/spec_helper.rb +10 -5
  53. data/spec/support/config.rb +10 -0
  54. data/spec/support/helpers/add_word.rb +20 -0
  55. data/spec/support/helpers/one_line_heredoc.rb +11 -0
  56. data/spec/support/shared_examples/a_compressible_trie.rb +40 -0
  57. data/spec/support/shared_examples/a_serializable_trie.rb +10 -6
  58. data/spec/support/shared_examples/a_serializer.rb +9 -1
  59. data/spec/support/shared_examples/a_trie_data_structure.rb +2 -0
  60. data/spec/support/shared_examples/a_trie_node.rb +127 -0
  61. data/spec/{lib/rambling/trie/compressed_node_spec.rb → support/shared_examples/a_trie_node_implementation.rb} +25 -72
  62. metadata +42 -31
  63. data/lib/rambling/trie/compressable.rb +0 -14
  64. data/lib/rambling/trie/compressed_node.rb +0 -120
  65. data/lib/rambling/trie/missing_node.rb +0 -8
  66. data/lib/rambling/trie/node.rb +0 -97
  67. data/lib/rambling/trie/raw_node.rb +0 -96
  68. data/spec/lib/rambling/trie/node_spec.rb +0 -86
  69. data/spec/lib/rambling/trie/raw_node_spec.rb +0 -389
  70. data/spec/support/shared_examples/a_compressable_trie.rb +0 -26
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Rambling::Trie::Configuration::ProviderCollection do
@@ -11,15 +13,15 @@ describe Rambling::Trie::Configuration::ProviderCollection do
11
13
 
12
14
  let(:provider_collection) do
13
15
  Rambling::Trie::Configuration::ProviderCollection.new(
14
- 'provider',
16
+ :provider,
15
17
  configured_providers,
16
- configured_default
18
+ configured_default,
17
19
  )
18
20
  end
19
21
 
20
22
  describe '.new' do
21
23
  it 'has a name' do
22
- expect(provider_collection.name).to eq 'provider'
24
+ expect(provider_collection.name).to eq :provider
23
25
  end
24
26
 
25
27
  it 'has the given providers' do
@@ -45,32 +47,20 @@ describe Rambling::Trie::Configuration::ProviderCollection do
45
47
 
46
48
  before do
47
49
  allow(providers) .to receive_messages(
48
- :[] => nil,
49
- :[]= => nil,
50
- keys: nil,
51
- values: nil,
50
+ :[] => 'value',
51
+ keys: %i(a b),
52
52
  )
53
53
  end
54
54
 
55
- it 'delegates #[] to providers' do
56
- provider_collection[:key]
55
+ it 'delegates `#[]` to providers' do
56
+ expect(provider_collection[:key]).to eq 'value'
57
57
  expect(providers).to have_received(:[]).with :key
58
58
  end
59
59
 
60
- it 'delegates #[]= to providers' do
61
- provider_collection[:key] = 'hello'
62
- expect(providers).to have_received(:[]=).with :key, 'hello'
63
- end
64
-
65
- it 'delegates #keys to providers' do
66
- provider_collection.keys
60
+ it 'aliases `#formats` to `providers#keys`' do
61
+ expect(provider_collection.formats).to eq %i(a b)
67
62
  expect(providers).to have_received :keys
68
63
  end
69
-
70
- it 'delegates #values to providers' do
71
- provider_collection.values
72
- expect(providers).to have_received :values
73
- end
74
64
  end
75
65
 
76
66
  describe '#add' do
@@ -96,26 +86,20 @@ describe Rambling::Trie::Configuration::ProviderCollection do
96
86
  end
97
87
 
98
88
  context 'when the given value is not in the providers list' do
99
- it 'does not change the default provider' do
100
- expect do
101
- begin
102
- provider_collection.default = other_provider
103
- rescue
104
- end
105
- end.not_to change { provider_collection.default }
89
+ it 'raises an error and keeps the default provider' do
90
+ expect { provider_collection.default = other_provider }
91
+ .to raise_error(ArgumentError)
92
+ .and(not_change { provider_collection.default })
106
93
  end
107
94
 
108
95
  it 'raises an ArgumentError' do
109
- expect do
110
- provider_collection.default = other_provider
111
- end.to raise_error ArgumentError
96
+ expect { provider_collection.default = other_provider }
97
+ .to raise_error ArgumentError
112
98
  end
113
99
  end
114
100
 
115
101
  context 'when the providers list is empty' do
116
- let(:configured_providers) do
117
- {}
118
- end
102
+ let(:configured_providers) { {} }
119
103
 
120
104
  it 'accepts nil' do
121
105
  provider_collection.default = nil
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Rambling::Trie::Container do
4
6
  let(:container) { Rambling::Trie::Container.new root, compressor }
5
7
  let(:compressor) { Rambling::Trie::Compressor.new }
6
- let(:root) { Rambling::Trie::RawNode.new }
8
+ let(:root) { Rambling::Trie::Nodes::Raw.new }
7
9
 
8
10
  describe '.new' do
9
11
  it 'uses the provided node as root' do
@@ -14,8 +16,8 @@ describe Rambling::Trie::Container do
14
16
  it 'yields the container' do
15
17
  yielded = nil
16
18
 
17
- container = Rambling::Trie::Container.new root, compressor do |container|
18
- yielded = container
19
+ container = Rambling::Trie::Container.new root, compressor do |c|
20
+ yielded = c
19
21
  end
20
22
 
21
23
  expect(yielded).to be container
@@ -24,40 +26,51 @@ describe Rambling::Trie::Container do
24
26
  end
25
27
 
26
28
  describe '#add' do
27
- let(:clone) { double :clone }
28
- let(:word) { double :word, clone: clone }
29
+ it 'adds the word to the root node' do
30
+ add_word container, 'hello'
29
31
 
30
- before do
31
- allow(root).to receive(:add)
32
+ expect(root.children.size).to eq 1
33
+ expect(root.to_a).to eq %w(hello)
34
+ end
35
+ end
36
+
37
+ describe '#concat' do
38
+ it 'adds all the words to the root node' do
39
+ container.concat %w(other words)
40
+
41
+ expect(root.children.size).to eq 2
42
+ expect(root.to_a).to eq %w(other words)
32
43
  end
33
44
 
34
- it 'clones the original word' do
35
- container.add word
36
- expect(root).to have_received(:add).with clone
45
+ it 'returns all the corresponding nodes' do
46
+ nodes = container.concat %w(other words)
47
+
48
+ expect(nodes.first.letter).to eq :o
49
+ expect(nodes.last.letter).to eq :w
37
50
  end
38
51
  end
39
52
 
40
53
  describe '#compress!' do
41
- let(:node) { double :node, add: nil, compressed?: false }
54
+ let(:node) { Rambling::Trie::Nodes::Compressed.new }
42
55
 
43
56
  before do
44
57
  allow(compressor).to receive(:compress).and_return node
45
- allow(root).to receive(:add)
58
+
59
+ add_word root, 'yes'
60
+ node[:yes] = Rambling::Trie::Nodes::Compressed.new
46
61
  end
47
62
 
48
63
  it 'compresses the trie using the compressor' do
49
64
  container.compress!
50
65
 
51
- expect(compressor).to have_received(:compress)
52
- .with root
66
+ expect(compressor).to have_received(:compress).with root
53
67
  end
54
68
 
55
69
  it 'changes to the root returned by the compressor' do
56
70
  container.compress!
57
- container.add 'word'
58
71
 
59
- expect(root).not_to have_received :add
60
- expect(node).to have_received :add
72
+ expect(container.root).not_to eq root
73
+ expect(container.root).to eq node
61
74
  end
62
75
 
63
76
  it 'returns itself' do
@@ -73,13 +86,57 @@ describe Rambling::Trie::Container do
73
86
  end
74
87
  end
75
88
 
89
+ describe '#compress' do
90
+ let(:node) { Rambling::Trie::Nodes::Compressed.new }
91
+
92
+ before do
93
+ allow(compressor).to receive(:compress).and_return node
94
+
95
+ add_word root, 'yes'
96
+ node[:yes] = Rambling::Trie::Nodes::Compressed.new
97
+ end
98
+
99
+ it 'compresses the trie using the compressor' do
100
+ container.compress
101
+
102
+ expect(compressor).to have_received(:compress).with root
103
+ end
104
+
105
+ it 'returns a container with the new root' do
106
+ new_container = container.compress
107
+
108
+ expect(new_container.root).not_to eq root
109
+ expect(new_container.root).to eq node
110
+ end
111
+
112
+ it 'returns a new container' do
113
+ expect(container.compress).not_to eq container
114
+ end
115
+
116
+ it 'can compress multiple times' do
117
+ container.compress
118
+ container.compress
119
+
120
+ expect(compressor).to have_received(:compress).twice
121
+ end
122
+
123
+ it 'cannot compress the result' do
124
+ new_container = container.compress
125
+ new_container.compress
126
+
127
+ expect(compressor).to have_received(:compress).once
128
+ end
129
+ end
130
+
76
131
  describe '#word?' do
132
+ let(:root) do
133
+ double :root,
134
+ compressed?: compressed,
135
+ word?: nil
136
+ end
137
+
77
138
  context 'for an uncompressed root' do
78
- let(:root) do
79
- double :root,
80
- compressed?: false,
81
- word?: nil
82
- end
139
+ let(:compressed) { true }
83
140
 
84
141
  it 'calls the root with the word characters' do
85
142
  container.word? 'words'
@@ -88,11 +145,7 @@ describe Rambling::Trie::Container do
88
145
  end
89
146
 
90
147
  context 'for a compressed root' do
91
- let(:root) do
92
- double :root,
93
- compressed?: true,
94
- word?: nil
95
- end
148
+ let(:compressed) { false }
96
149
 
97
150
  it 'calls the root with the full word' do
98
151
  container.word? 'words'
@@ -102,12 +155,14 @@ describe Rambling::Trie::Container do
102
155
  end
103
156
 
104
157
  describe '#partial_word?' do
158
+ let(:root) do
159
+ double :root,
160
+ compressed?: compressed,
161
+ partial_word?: nil
162
+ end
163
+
105
164
  context 'for an uncompressed root' do
106
- let(:root) do
107
- double :root,
108
- compressed?: false,
109
- partial_word?: nil
110
- end
165
+ let(:compressed) { true }
111
166
 
112
167
  it 'calls the root with the word characters' do
113
168
  container.partial_word? 'words'
@@ -116,11 +171,7 @@ describe Rambling::Trie::Container do
116
171
  end
117
172
 
118
173
  context 'for a compressed root' do
119
- let(:root) do
120
- double :root,
121
- compressed?: true,
122
- partial_word?: nil
123
- end
174
+ let(:compressed) { false }
124
175
 
125
176
  it 'calls the root with the word characters' do
126
177
  container.partial_word? 'words'
@@ -139,7 +190,7 @@ describe Rambling::Trie::Container do
139
190
  children_tree: nil,
140
191
  compressed?: nil,
141
192
  each: nil,
142
- has_key?: nil,
193
+ key?: nil,
143
194
  inspect: nil,
144
195
  letter: nil,
145
196
  parent: nil,
@@ -168,17 +219,12 @@ describe Rambling::Trie::Container do
168
219
 
169
220
  it 'aliases `#<<` to `#add`' do
170
221
  container << 'words'
171
- expect(root).to have_received(:add).with 'words'
222
+ expect(root).to have_received(:add).with %i(s d r o w)
172
223
  end
173
224
 
174
225
  it 'delegates `#[]` to the root node' do
175
- container.[]
176
- expect(root).to have_received :[]
177
- end
178
-
179
- it 'delegates `#as_word` to the root node' do
180
- container.as_word
181
- expect(root).to have_received :as_word
226
+ container[:yep]
227
+ expect(root).to have_received(:[]).with :yep
182
228
  end
183
229
 
184
230
  it 'delegates `#children` to the root node' do
@@ -196,14 +242,19 @@ describe Rambling::Trie::Container do
196
242
  expect(root).to have_received :compressed?
197
243
  end
198
244
 
199
- it 'delegates `#each` to the root node' do
200
- container.each
201
- expect(root).to have_received :each
245
+ it 'delegates `#key?` to the root node' do
246
+ container.key? :yup
247
+ expect(root).to have_received(:key?).with :yup
202
248
  end
203
249
 
204
- it 'delegates `#has_key?` to the root node' do
205
- container.has_key?
206
- expect(root).to have_received :has_key?
250
+ it 'aliases `#has_key?` to `#key?`' do
251
+ container.has_key? :yup
252
+ expect(root).to have_received(:key?).with :yup
253
+ end
254
+
255
+ it 'aliases `#has_letter?` to `#has_key?`' do
256
+ container.has_letter? :yup
257
+ expect(root).to have_received(:key?).with :yup
207
258
  end
208
259
 
209
260
  it 'delegates `#inspect` to the root node' do
@@ -211,140 +262,48 @@ describe Rambling::Trie::Container do
211
262
  expect(root).to have_received :inspect
212
263
  end
213
264
 
214
- it 'delegates `#letter` to the root node' do
215
- container.letter
216
- expect(root).to have_received :letter
217
- end
218
-
219
- it 'delegates `#parent` to the root node' do
220
- container.parent
221
- expect(root).to have_received :parent
222
- end
223
-
224
265
  it 'delegates `#size` to the root node' do
225
266
  container.size
226
267
  expect(root).to have_received :size
227
268
  end
228
-
229
- it 'delegates `#to_s` to the root node' do
230
- container.to_s
231
- expect(root).to have_received :to_s
232
- end
233
269
  end
234
270
 
235
271
  describe '#compress!' do
236
- let(:compressor) { Rambling::Trie::Compressor.new }
237
- let(:root) { Rambling::Trie::RawNode.new }
238
-
239
- context 'with at least one word' do
240
- it 'keeps the root letter nil' do
241
- container.add 'all'
242
- container.compress!
243
-
244
- expect(container.letter).to be_nil
245
- end
246
- end
247
-
248
- context 'with a single word' do
249
- before do
250
- container.add 'all'
251
- container.compress!
252
- end
253
-
254
- it 'compresses into a single node without children' do
255
- expect(container[:all].letter).to eq :all
256
- expect(container[:all].children.size).to eq 0
257
- expect(container[:all]).to be_terminal
258
- expect(container[:all]).to be_compressed
259
- end
260
- end
261
-
262
- context 'with two words' do
263
- before do
264
- container.add 'all'
265
- container.add 'ask'
266
- container.compress!
267
- end
268
-
269
- it 'compresses into corresponding three nodes' do
270
- expect(container[:a].letter).to eq :a
271
- expect(container[:a].children.size).to eq 2
272
-
273
- expect(container[:a][:ll].letter).to eq :ll
274
- expect(container[:a][:sk].letter).to eq :sk
275
-
276
- expect(container[:a][:ll].children.size).to eq 0
277
- expect(container[:a][:sk].children.size).to eq 0
278
-
279
- expect(container[:a][:ll]).to be_terminal
280
- expect(container[:a][:sk]).to be_terminal
281
-
282
- expect(container[:a][:ll]).to be_compressed
283
- expect(container[:a][:sk]).to be_compressed
284
- end
285
- end
286
-
287
- it 'reassigns the parent nodes correctly' do
288
- container.add 'repay'
289
- container.add 'rest'
290
- container.add 'repaint'
272
+ it 'gets a new root from the compressor' do
291
273
  container.compress!
292
274
 
293
- expect(container[:re].letter).to eq :re
294
- expect(container[:re].children.size).to eq 2
295
-
296
- expect(container[:re][:pa].letter).to eq :pa
297
- expect(container[:re][:st].letter).to eq :st
298
-
299
- expect(container[:re][:pa].children.size).to eq 2
300
- expect(container[:re][:st].children.size).to eq 0
301
-
302
- expect(container[:re][:pa][:y].letter).to eq :y
303
- expect(container[:re][:pa][:int].letter).to eq :int
304
-
305
- expect(container[:re][:pa][:y].children.size).to eq 0
306
- expect(container[:re][:pa][:int].children.size).to eq 0
307
-
308
- expect(container[:re][:pa][:y].parent).to eq container[:re][:pa]
309
- expect(container[:re][:pa][:int].parent).to eq container[:re][:pa]
275
+ expect(container.root).not_to be root
276
+ expect(container.root).to be_compressed
277
+ expect(root).not_to be_compressed
310
278
  end
311
279
 
312
- it 'does not compress terminal nodes' do
313
- container.add 'you'
314
- container.add 'your'
315
- container.add 'yours'
280
+ it 'generates a new root with the words from the passed root' do
281
+ words = %w(a few words hello hell)
316
282
 
283
+ add_words container, words
317
284
  container.compress!
318
285
 
319
- expect(container[:you].letter).to eq :you
320
-
321
- expect(container[:you][:r].letter).to eq :r
322
- expect(container[:you][:r]).to be_compressed
323
-
324
- expect(container[:you][:r][:s].letter).to eq :s
325
- expect(container[:you][:r][:s]).to be_compressed
286
+ words.each do |word|
287
+ expect(container).to include word
288
+ end
326
289
  end
327
290
 
328
291
  describe 'and trying to add a word' do
329
292
  it 'raises an error' do
330
- container.add 'repay'
331
- container.add 'rest'
332
- container.add 'repaint'
293
+ add_words container, %w(repay rest repaint)
333
294
  container.compress!
334
295
 
335
- expect { container.add 'restaurant' }.to raise_error Rambling::Trie::InvalidOperation
296
+ expect do
297
+ add_word container, 'restaurant'
298
+ end.to raise_error Rambling::Trie::InvalidOperation
336
299
  end
337
300
  end
338
301
  end
339
302
 
340
303
  describe '#word?' do
341
- let(:compressor) { Rambling::Trie::Compressor.new }
342
- let(:root) { Rambling::Trie::RawNode.new }
343
-
344
304
  context 'word is contained' do
345
305
  before do
346
- container.add 'hello'
347
- container.add 'high'
306
+ add_words container, %w(hello high)
348
307
  end
349
308
 
350
309
  it 'matches the whole word' do
@@ -366,7 +325,7 @@ describe Rambling::Trie::Container do
366
325
 
367
326
  context 'word is not contained' do
368
327
  before do
369
- container.add 'hello'
328
+ add_word container, 'hello'
370
329
  end
371
330
 
372
331
  it 'does not match the whole word' do
@@ -390,8 +349,7 @@ describe Rambling::Trie::Container do
390
349
  describe '#partial_word?' do
391
350
  context 'word is contained' do
392
351
  before do
393
- container.add 'hello'
394
- container.add 'high'
352
+ add_words container, %w(hello high)
395
353
  end
396
354
 
397
355
  it 'matches part of the word' do
@@ -416,27 +374,25 @@ describe Rambling::Trie::Container do
416
374
  end
417
375
  end
418
376
 
377
+ shared_examples_for 'a non matching tree' do
378
+ it 'does not match any part of the word' do
379
+ %w(ha hal al).each do |word|
380
+ expect(container.partial_word? word).to be false
381
+ end
382
+ end
383
+ end
384
+
419
385
  context 'word is not contained' do
420
386
  before do
421
- container.add 'hello'
387
+ add_word container, 'hello'
422
388
  end
423
389
 
424
- it 'does not match any part of the word' do
425
- expect(container.partial_word? 'ha').to be false
426
- expect(container.partial_word? 'hal').to be false
427
- expect(container.partial_word? 'al').to be false
390
+ context 'and the root is uncompressed' do
391
+ it_behaves_like 'a non matching tree'
428
392
  end
429
393
 
430
394
  context 'and the root has been compressed' do
431
- before do
432
- container.compress!
433
- end
434
-
435
- it 'does not match any part of the word' do
436
- expect(container.partial_word? 'ha').to be false
437
- expect(container.partial_word? 'hal').to be false
438
- expect(container.partial_word? 'al').to be false
439
- end
395
+ it_behaves_like 'a non matching tree'
440
396
  end
441
397
  end
442
398
  end
@@ -444,23 +400,12 @@ describe Rambling::Trie::Container do
444
400
  describe '#scan' do
445
401
  context 'words that match are not contained' do
446
402
  before do
447
- %w(hi hello high hell highlight histerical).each do |word|
448
- container.add word
449
- end
403
+ add_words container, %w(hi hello high hell highlight histerical)
450
404
  end
451
405
 
452
406
  it 'returns an array with the words that match' do
453
- expect(container.scan 'hi').to eq [
454
- 'hi',
455
- 'high',
456
- 'highlight',
457
- 'histerical'
458
- ]
459
-
460
- expect(container.scan 'hig').to eq [
461
- 'high',
462
- 'highlight'
463
- ]
407
+ expect(container.scan 'hi').to eq %w(hi high highlight histerical)
408
+ expect(container.scan 'hig').to eq %w(high highlight)
464
409
  end
465
410
 
466
411
  context 'and the root has been compressed' do
@@ -469,28 +414,19 @@ describe Rambling::Trie::Container do
469
414
  end
470
415
 
471
416
  it 'returns an array with the words that match' do
472
- expect(container.scan 'hi').to eq [
473
- 'hi',
474
- 'high',
475
- 'highlight',
476
- 'histerical'
477
- ]
478
-
479
- expect(container.scan 'hig').to eq [
480
- 'high',
481
- 'highlight'
482
- ]
417
+ expect(container.scan 'hi').to eq %w(hi high highlight histerical)
418
+ expect(container.scan 'hig').to eq %w(high highlight)
483
419
  end
484
420
  end
485
421
  end
486
422
 
487
423
  context 'words that match are not contained' do
488
424
  before do
489
- container.add 'hello'
425
+ add_word container, 'hello'
490
426
  end
491
427
 
492
428
  it 'returns an empty array' do
493
- expect(container.scan 'hi').to eq []
429
+ expect(container.scan 'hi').to eq %w()
494
430
  end
495
431
 
496
432
  context 'and the root has been compressed' do
@@ -499,7 +435,7 @@ describe Rambling::Trie::Container do
499
435
  end
500
436
 
501
437
  it 'returns an empty array' do
502
- expect(container.scan 'hi').to eq []
438
+ expect(container.scan 'hi').to eq %w()
503
439
  end
504
440
  end
505
441
  end
@@ -507,9 +443,7 @@ describe Rambling::Trie::Container do
507
443
 
508
444
  describe '#words_within' do
509
445
  before do
510
- %w(one word and other words).each do |word|
511
- container.add word
512
- end
446
+ add_words container, %w(one word and other words)
513
447
  end
514
448
 
515
449
  context 'phrase does not contain any words' do
@@ -564,7 +498,8 @@ describe Rambling::Trie::Container do
564
498
 
565
499
  context 'phrase contains a few words' do
566
500
  it 'returns an array with all words found in the phrase' do
567
- expect(container.words_within 'xyzword otherzxyone').to match_array %w(word other one)
501
+ expect(container.words_within 'xyzword otherzxyone')
502
+ .to match_array %w(word other one)
568
503
  end
569
504
 
570
505
  context 'and the node is compressed' do
@@ -573,7 +508,8 @@ describe Rambling::Trie::Container do
573
508
  end
574
509
 
575
510
  it 'returns an array with all words found in the phrase' do
576
- expect(container.words_within 'xyzword otherzxyone').to match_array %w(word other one)
511
+ expect(container.words_within 'xyzword otherzxyone')
512
+ .to match_array %w(word other one)
577
513
  end
578
514
  end
579
515
  end
@@ -581,9 +517,7 @@ describe Rambling::Trie::Container do
581
517
 
582
518
  describe '#words_within?' do
583
519
  before do
584
- %w(one word and other words).each do |word|
585
- container.add word
586
- end
520
+ add_words container, %w(one word and other words)
587
521
  end
588
522
 
589
523
  context 'phrase does not contain any words' do
@@ -602,7 +536,9 @@ describe Rambling::Trie::Container do
602
536
 
603
537
  describe '#==' do
604
538
  context 'when the root nodes are the same' do
605
- let(:other_container) { Rambling::Trie::Container.new container.root, compressor }
539
+ let(:other_container) do
540
+ Rambling::Trie::Container.new container.root, compressor
541
+ end
606
542
 
607
543
  it 'returns true' do
608
544
  expect(container).to eq other_container
@@ -610,11 +546,13 @@ describe Rambling::Trie::Container do
610
546
  end
611
547
 
612
548
  context 'when the root nodes are not the same' do
613
- let(:other_root) { Rambling::Trie::RawNode.new }
549
+ let(:other_root) { Rambling::Trie::Nodes::Raw.new }
614
550
  let(:other_container) do
615
- Rambling::Trie::Container.new other_root, compressor do |c|
616
- c << 'hola'
617
- end
551
+ Rambling::Trie::Container.new other_root, compressor
552
+ end
553
+
554
+ before do
555
+ add_word other_container, 'hola'
618
556
  end
619
557
 
620
558
  it 'returns false' do
@@ -622,4 +560,32 @@ describe Rambling::Trie::Container do
622
560
  end
623
561
  end
624
562
  end
563
+
564
+ describe '#each' do
565
+ before do
566
+ add_words container, %w(yes no why)
567
+ end
568
+
569
+ it 'returns an enumerator when no block is given' do
570
+ expect(container.each).to be_instance_of Enumerator
571
+ end
572
+
573
+ it 'iterates through all words contained' do
574
+ expect(container.each.to_a).to eq %w(yes no why)
575
+ end
576
+ end
577
+
578
+ describe '#inspect' do
579
+ before do
580
+ add_words container, %w(a few words hello hell)
581
+ end
582
+
583
+ it 'returns the container class name plus the root inspection' do
584
+ expect(container.inspect).to eq one_line <<~CONTAINER
585
+ #<Rambling::Trie::Container root: #<Rambling::Trie::Nodes::Raw letter: nil,
586
+ terminal: nil,
587
+ children: [:a, :f, :w, :h]>>
588
+ CONTAINER
589
+ end
590
+ end
625
591
  end