rambling-trie 1.0.1 → 2.1.1

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.
Files changed (71) 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 +40 -33
  63. data/lib/rambling/trie/compressable.rb +0 -14
  64. data/lib/rambling/trie/compressed_node.rb +0 -120
  65. data/lib/rambling/trie/forwardable.rb +0 -21
  66. data/lib/rambling/trie/missing_node.rb +0 -8
  67. data/lib/rambling/trie/node.rb +0 -97
  68. data/lib/rambling/trie/raw_node.rb +0 -96
  69. data/spec/lib/rambling/trie/node_spec.rb +0 -86
  70. data/spec/lib/rambling/trie/raw_node_spec.rb +0 -389
  71. 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