rambling-trie 2.4.0 → 2.5.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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -0
  3. data/README.md +16 -10
  4. data/lib/rambling/trie/compressor.rb +2 -0
  5. data/lib/rambling/trie/configuration/properties.rb +5 -2
  6. data/lib/rambling/trie/configuration/provider_collection.rb +2 -2
  7. data/lib/rambling/trie/container.rb +12 -1
  8. data/lib/rambling/trie/enumerable.rb +1 -1
  9. data/lib/rambling/trie/nodes/node.rb +4 -4
  10. data/lib/rambling/trie/nodes/raw.rb +2 -1
  11. data/lib/rambling/trie/readers/plain_text.rb +1 -1
  12. data/lib/rambling/trie/serializers/file.rb +1 -3
  13. data/lib/rambling/trie/serializers/marshal.rb +3 -3
  14. data/lib/rambling/trie/serializers/yaml.rb +2 -2
  15. data/lib/rambling/trie/serializers/zip.rb +2 -0
  16. data/lib/rambling/trie/version.rb +1 -1
  17. data/lib/rambling/trie.rb +1 -1
  18. data/rambling-trie.gemspec +3 -9
  19. metadata +7 -122
  20. data/spec/assets/test_words.en_US.txt +0 -23
  21. data/spec/assets/test_words.es_DO.txt +0 -24
  22. data/spec/integration/rambling/trie_spec.rb +0 -116
  23. data/spec/lib/rambling/trie/comparable_spec.rb +0 -87
  24. data/spec/lib/rambling/trie/compressor_spec.rb +0 -111
  25. data/spec/lib/rambling/trie/configuration/properties_spec.rb +0 -75
  26. data/spec/lib/rambling/trie/configuration/provider_collection_spec.rb +0 -177
  27. data/spec/lib/rambling/trie/container_spec.rb +0 -466
  28. data/spec/lib/rambling/trie/enumerable_spec.rb +0 -50
  29. data/spec/lib/rambling/trie/inspectable_spec.rb +0 -62
  30. data/spec/lib/rambling/trie/nodes/compressed_spec.rb +0 -43
  31. data/spec/lib/rambling/trie/nodes/node_spec.rb +0 -9
  32. data/spec/lib/rambling/trie/nodes/raw_spec.rb +0 -184
  33. data/spec/lib/rambling/trie/readers/plain_text_spec.rb +0 -26
  34. data/spec/lib/rambling/trie/readers/reader_spec.rb +0 -14
  35. data/spec/lib/rambling/trie/serializers/file_spec.rb +0 -11
  36. data/spec/lib/rambling/trie/serializers/marshal_spec.rb +0 -10
  37. data/spec/lib/rambling/trie/serializers/serializer_spec.rb +0 -21
  38. data/spec/lib/rambling/trie/serializers/yaml_spec.rb +0 -10
  39. data/spec/lib/rambling/trie/serializers/zip_spec.rb +0 -36
  40. data/spec/lib/rambling/trie/stringifyable_spec.rb +0 -89
  41. data/spec/lib/rambling/trie_spec.rb +0 -244
  42. data/spec/spec_helper.rb +0 -42
  43. data/spec/support/config.rb +0 -15
  44. data/spec/support/helpers/add_word.rb +0 -20
  45. data/spec/support/helpers/one_line_heredoc.rb +0 -11
  46. data/spec/support/shared_examples/a_compressible_trie.rb +0 -46
  47. data/spec/support/shared_examples/a_container_partial_word.rb +0 -17
  48. data/spec/support/shared_examples/a_container_scan.rb +0 -14
  49. data/spec/support/shared_examples/a_container_word.rb +0 -43
  50. data/spec/support/shared_examples/a_container_words_within.rb +0 -44
  51. data/spec/support/shared_examples/a_serializable_trie.rb +0 -26
  52. data/spec/support/shared_examples/a_serializer.rb +0 -60
  53. data/spec/support/shared_examples/a_trie_data_structure.rb +0 -45
  54. data/spec/support/shared_examples/a_trie_node.rb +0 -135
  55. data/spec/support/shared_examples/a_trie_node_implementation.rb +0 -149
  56. data/spec/tmp/.gitkeep +0 -0
@@ -1,116 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
- require 'zip'
5
-
6
- describe Rambling::Trie do
7
- let(:assets_path) { File.join ::SPEC_ROOT, 'assets' }
8
-
9
- describe '::VERSION' do
10
- let(:root_path) { File.join ::SPEC_ROOT, '..' }
11
- let(:readme_path) { File.join root_path, 'README.md' }
12
- let(:readme) { File.read readme_path }
13
- let(:changelog_path) { File.join root_path, 'CHANGELOG.md' }
14
- let(:changelog) { File.read changelog_path }
15
-
16
- let(:changelog_versions) do
17
- matches = []
18
- changelog.scan %r{^## (\d+\.\d+\.\d+)} do |match|
19
- matches << match[0]
20
- end
21
- matches
22
- end
23
-
24
- it 'matches with the version in the README badge' do
25
- match = %r{\?version=(?<version>.*)$}.match readme
26
- expect(match['version']).to eq Rambling::Trie::VERSION
27
- end
28
-
29
- it 'is the version before the one at the top of the CHANGELOG' do
30
- changelog_version = Gem::Version.new changelog_versions.first
31
- lib_version = Gem::Version.new "#{Rambling::Trie::VERSION}.0"
32
- expect(changelog_version).to eq lib_version.bump
33
- end
34
-
35
- it 'is included in the CHANGELOG diffs' do
36
- changelog_versions.shift
37
- expect(changelog_versions.first).to eq Rambling::Trie::VERSION
38
- end
39
- end
40
-
41
- context 'when providing words directly' do
42
- it_behaves_like 'a compressible trie' do
43
- let(:trie) { described_class.create }
44
- let(:words) { %w(a couple of words for our full trie integration test) }
45
-
46
- before { trie.concat words }
47
- end
48
- end
49
-
50
- context 'when provided with words with unicode characters' do
51
- it_behaves_like 'a compressible trie' do
52
- let(:trie) { described_class.create }
53
- let :words do
54
- %w(poquísimas palabras para nuestra prueba de integración completa 🙃)
55
- end
56
-
57
- before { trie.concat words }
58
- end
59
- end
60
-
61
- context 'when provided with a filepath' do
62
- let(:trie) { described_class.create filepath }
63
- let(:words) { File.readlines(filepath).map(&:chomp) }
64
-
65
- context 'with english words' do
66
- it_behaves_like 'a compressible trie' do
67
- let(:filepath) { File.join assets_path, 'test_words.en_US.txt' }
68
- end
69
- end
70
-
71
- context 'with unicode characters' do
72
- it_behaves_like 'a compressible trie' do
73
- let(:filepath) { File.join assets_path, 'test_words.es_DO.txt' }
74
- end
75
- end
76
- end
77
-
78
- describe 'dump and load' do
79
- let(:words_filepath) { File.join assets_path, 'test_words.en_US.txt' }
80
- let(:words) { File.readlines(words_filepath).map(&:chomp) }
81
-
82
- context 'when serialized with Ruby marshal format (default)' do
83
- it_behaves_like 'a serializable trie' do
84
- let(:trie_to_serialize) { described_class.create words_filepath }
85
- let(:file_format) { :marshal }
86
- end
87
- end
88
-
89
- context 'when serialized with YAML' do
90
- it_behaves_like 'a serializable trie' do
91
- let(:trie_to_serialize) { described_class.create words_filepath }
92
- let(:file_format) { :yml }
93
- end
94
- end
95
-
96
- context 'when serialized with zipped Ruby marshal format' do
97
- let!(:original_on_exists_proc) { ::Zip.on_exists_proc }
98
- let!(:original_continue_on_exists_proc) { ::Zip.continue_on_exists_proc }
99
-
100
- before do
101
- ::Zip.on_exists_proc = true
102
- ::Zip.continue_on_exists_proc = true
103
- end
104
-
105
- after do
106
- ::Zip.on_exists_proc = original_on_exists_proc
107
- ::Zip.continue_on_exists_proc = original_continue_on_exists_proc
108
- end
109
-
110
- it_behaves_like 'a serializable trie' do
111
- let(:trie_to_serialize) { described_class.create words_filepath }
112
- let(:file_format) { 'marshal.zip' }
113
- end
114
- end
115
- end
116
- end
@@ -1,87 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- describe Rambling::Trie::Comparable do
6
- describe '#==' do
7
- let(:node_one) { Rambling::Trie::Nodes::Raw.new }
8
- let(:node_two) { Rambling::Trie::Nodes::Raw.new }
9
-
10
- context 'when the nodes do not have the same letter' do
11
- before do
12
- node_one.letter = :a
13
- node_two.letter = :b
14
- end
15
-
16
- it 'returns false' do
17
- expect(node_one).not_to eq node_two
18
- end
19
- end
20
-
21
- context 'when nodes have same letter, not terminal and no children' do
22
- before do
23
- node_one.letter = :a
24
- node_two.letter = :a
25
- end
26
-
27
- it 'returns true' do
28
- expect(node_one).to eq node_two
29
- end
30
- end
31
-
32
- context 'when the nodes have the same letter and are terminal' do
33
- before do
34
- node_one.letter = :a
35
- node_one.terminal!
36
-
37
- node_two.letter = :a
38
- node_two.terminal!
39
- end
40
-
41
- it 'returns true' do
42
- expect(node_one).to eq node_two
43
- end
44
- end
45
-
46
- context 'when the nodes have the same letter but are not both terminal' do
47
- before do
48
- node_one.letter = :a
49
- node_one.terminal!
50
-
51
- node_two.letter = :a
52
- end
53
-
54
- it 'returns false' do
55
- expect(node_one).not_to eq node_two
56
- end
57
- end
58
-
59
- context 'when the nodes have the same letter and the same children' do
60
- before do
61
- node_one.letter = :t
62
- add_words node_one, %w(hese hree hings)
63
-
64
- node_two.letter = :t
65
- add_words node_two, %w(hese hree hings)
66
- end
67
-
68
- it 'returns true' do
69
- expect(node_one).to eq node_two
70
- end
71
- end
72
-
73
- context 'when the nodes have the same letter but different children' do
74
- before do
75
- node_one.letter = :t
76
- add_words node_one, %w(hese wo)
77
-
78
- node_two.letter = :t
79
- add_words node_two, %w(hese hree hings)
80
- end
81
-
82
- it 'returns false' do
83
- expect(node_one).not_to eq node_two
84
- end
85
- end
86
- end
87
- end
@@ -1,111 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- describe Rambling::Trie::Compressor do
6
- let(:compressor) { described_class.new }
7
-
8
- describe '#compress' do
9
- let(:node) { Rambling::Trie::Nodes::Raw.new }
10
-
11
- it 'compresses the node' do
12
- add_words node, %w(a few words hello hell)
13
- compressed = compressor.compress node
14
-
15
- expect(compressed.children_tree.keys).to eq %i(a f w h)
16
- end
17
-
18
- context 'with at least one word' do
19
- before { add_words node, %w(all the words) }
20
-
21
- it 'keeps the node letter nil' do
22
- compressed = compressor.compress node
23
-
24
- expect(compressed.letter).to be_nil
25
- end
26
- end
27
-
28
- context 'with a single word' do
29
- before { add_word node, 'all' }
30
-
31
- # rubocop:disable RSpec/ExampleLength, RSpec/MultipleExpectations
32
- it 'compresses into a single node without children' do
33
- compressed = compressor.compress node
34
- compressed_node_a = compressed[:a]
35
-
36
- expect(compressed_node_a.letter).to eq :all
37
- expect(compressed_node_a.children.size).to eq 0
38
- expect(compressed_node_a).to be_terminal
39
- expect(compressed_node_a).to be_compressed
40
- end
41
- # rubocop:enable RSpec/ExampleLength, RSpec/MultipleExpectations
42
- end
43
-
44
- context 'with two words' do
45
- before { add_words node, %w(all ask) }
46
-
47
- # rubocop:disable RSpec/ExampleLength, RSpec/MultipleExpectations
48
- it 'compresses into corresponding three nodes' do
49
- compressed = compressor.compress node
50
-
51
- expect(compressed[:a].letter).to eq :a
52
- expect(compressed[:a].children.size).to eq 2
53
-
54
- expect(compressed[:a][:l].letter).to eq :ll
55
- expect(compressed[:a][:s].letter).to eq :sk
56
-
57
- expect(compressed[:a][:l].children.size).to eq 0
58
- expect(compressed[:a][:s].children.size).to eq 0
59
-
60
- expect(compressed[:a][:l]).to be_terminal
61
- expect(compressed[:a][:s]).to be_terminal
62
-
63
- expect(compressed[:a][:l]).to be_compressed
64
- expect(compressed[:a][:s]).to be_compressed
65
- end
66
- # rubocop:enable RSpec/ExampleLength, RSpec/MultipleExpectations
67
- end
68
-
69
- # rubocop:disable RSpec/ExampleLength, RSpec/MultipleExpectations
70
- it 'reassigns the parent nodes correctly' do
71
- add_words node, %w(repay rest repaint)
72
- compressed = compressor.compress node
73
-
74
- expect(compressed[:r].letter).to eq :re
75
- expect(compressed[:r].parent).to eq compressed
76
- expect(compressed[:r].children.size).to eq 2
77
-
78
- expect(compressed[:r][:p].letter).to eq :pa
79
- expect(compressed[:r][:p].parent).to eq compressed[:r]
80
- expect(compressed[:r][:p].children.size).to eq 2
81
-
82
- expect(compressed[:r][:s].letter).to eq :st
83
- expect(compressed[:r][:s].parent).to eq compressed[:r]
84
- expect(compressed[:r][:s].children.size).to eq 0
85
-
86
- expect(compressed[:r][:p][:y].letter).to eq :y
87
- expect(compressed[:r][:p][:y].parent).to eq compressed[:r][:p]
88
- expect(compressed[:r][:p][:y].children.size).to eq 0
89
-
90
- expect(compressed[:r][:p][:i].letter).to eq :int
91
- expect(compressed[:r][:p][:i].parent).to eq compressed[:r][:p]
92
- expect(compressed[:r][:p][:i].children.size).to eq 0
93
- end
94
- # rubocop:enable RSpec/ExampleLength, RSpec/MultipleExpectations
95
-
96
- # rubocop:disable RSpec/ExampleLength, RSpec/MultipleExpectations
97
- it 'does not compress terminal nodes' do
98
- add_words node, %w(you your yours)
99
- compressed = compressor.compress node
100
-
101
- expect(compressed[:y].letter).to eq :you
102
-
103
- expect(compressed[:y][:r].letter).to eq :r
104
- expect(compressed[:y][:r]).to be_compressed
105
-
106
- expect(compressed[:y][:r][:s].letter).to eq :s
107
- expect(compressed[:y][:r][:s]).to be_compressed
108
- end
109
- # rubocop:enable RSpec/ExampleLength, RSpec/MultipleExpectations
110
- end
111
- end
@@ -1,75 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- describe Rambling::Trie::Configuration::Properties do
6
- let(:properties) { described_class.new }
7
-
8
- describe '.new' do
9
- it 'configures the serializer formats' do
10
- serializers = properties.serializers
11
- expect(serializers.formats).to match_array %i(marshal yaml yml zip)
12
- end
13
-
14
- # rubocop:disable RSpec/ExampleLength
15
- it 'configures the serializer providers' do
16
- serializers = properties.serializers
17
- expect(serializers.providers.to_a).to match_array [
18
- [:marshal, Rambling::Trie::Serializers::Marshal],
19
- [:yaml, Rambling::Trie::Serializers::Yaml],
20
- [:yml, Rambling::Trie::Serializers::Yaml],
21
- [:zip, Rambling::Trie::Serializers::Zip],
22
- ]
23
- end
24
- # rubocop:enable RSpec/ExampleLength
25
-
26
- it 'configures the reader formats' do
27
- readers = properties.readers
28
- expect(readers.formats).to match_array %i(txt)
29
- end
30
-
31
- it 'configures the reader providers' do
32
- readers = properties.readers
33
- expect(readers.providers.to_a).to match_array [
34
- [:txt, Rambling::Trie::Readers::PlainText],
35
- ]
36
- end
37
-
38
- it 'configures the compressor' do
39
- compressor = properties.compressor
40
- expect(compressor).to be_instance_of Rambling::Trie::Compressor
41
- end
42
-
43
- it 'configures the root_builder' do
44
- root = properties.root_builder.call
45
- expect(root).to be_instance_of Rambling::Trie::Nodes::Raw
46
- end
47
- end
48
-
49
- describe '#reset' do
50
- before do
51
- properties.serializers.add :test, 'test'
52
- properties.readers.add :test, 'test'
53
- end
54
-
55
- # rubocop:disable RSpec/MultipleExpectations
56
- it 'resets the serializers to initial values' do
57
- expect(properties.serializers.formats).to include :test
58
-
59
- properties.reset
60
-
61
- expect(properties.serializers.formats).not_to include :test
62
- end
63
- # rubocop:enable RSpec/MultipleExpectations
64
-
65
- # rubocop:disable RSpec/MultipleExpectations
66
- it 'resets the readers to initial values' do
67
- expect(properties.readers.formats).to include :test
68
-
69
- properties.reset
70
-
71
- expect(properties.readers.formats).not_to include :test
72
- end
73
- # rubocop:enable RSpec/MultipleExpectations
74
- end
75
- end
@@ -1,177 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- describe Rambling::Trie::Configuration::ProviderCollection do
6
- let(:configured_default) { nil }
7
- let :configured_providers do
8
- { one: first_provider, two: second_provider }
9
- end
10
-
11
- let :first_provider do
12
- instance_double 'Rambling::Trie::Serializers::Marshal', :first_provider
13
- end
14
- let :second_provider do
15
- instance_double 'Rambling::Trie::Serializers::Marshal', :second_provider
16
- end
17
-
18
- let :provider_collection do
19
- described_class.new(
20
- :provider,
21
- configured_providers,
22
- configured_default,
23
- )
24
- end
25
-
26
- describe '.new' do
27
- it 'has a name' do
28
- expect(provider_collection.name).to eq :provider
29
- end
30
-
31
- it 'has the given providers' do
32
- expect(provider_collection.providers)
33
- .to eq one: first_provider, two: second_provider
34
- end
35
-
36
- it 'has a default provider' do
37
- expect(provider_collection.default).to eq first_provider
38
- end
39
-
40
- context 'when a default is provided' do
41
- let(:configured_default) { second_provider }
42
-
43
- it 'has that as the default provider' do
44
- expect(provider_collection.default).to eq second_provider
45
- end
46
- end
47
- end
48
-
49
- describe 'aliases and delegates' do
50
- let(:providers) { provider_collection.providers }
51
-
52
- before do
53
- allow(providers).to receive_messages(
54
- :[] => 'value',
55
- keys: %i(a b),
56
- )
57
- end
58
-
59
- # rubocop:disable RSpec/MultipleExpectations
60
- it 'delegates `#[]` to providers' do
61
- expect(provider_collection[:key]).to eq 'value'
62
- expect(providers).to have_received(:[]).with :key
63
- end
64
- # rubocop:enable RSpec/MultipleExpectations
65
-
66
- # rubocop:disable RSpec/MultipleExpectations
67
- it 'aliases `#formats` to `providers#keys`' do
68
- expect(provider_collection.formats).to eq %i(a b)
69
- expect(providers).to have_received :keys
70
- end
71
- # rubocop:enable RSpec/MultipleExpectations
72
- end
73
-
74
- describe '#add' do
75
- let :provider do
76
- instance_double 'Rambling::Trie::Serializers::Marshal', :provider
77
- end
78
-
79
- before do
80
- provider_collection.add :three, provider
81
- end
82
-
83
- it 'adds a new provider' do
84
- expect(provider_collection.providers[:three]).to eq provider
85
- end
86
- end
87
-
88
- describe '#default=' do
89
- let :other_provider do
90
- instance_double 'Rambling::Trie::Serializers::Marshal', :other_provider
91
- end
92
-
93
- context 'when the given value is in the providers list' do
94
- it 'changes the default provider' do
95
- provider_collection.default = second_provider
96
- expect(provider_collection.default).to eq second_provider
97
- end
98
- end
99
-
100
- context 'when the given value is not in the providers list' do
101
- it 'raises an error and keeps the default provider' do
102
- expect { provider_collection.default = other_provider }
103
- .to raise_error(ArgumentError)
104
- .and(not_change { provider_collection.default })
105
- end
106
-
107
- it 'raises an ArgumentError' do
108
- expect { provider_collection.default = other_provider }
109
- .to raise_error ArgumentError
110
- end
111
- end
112
-
113
- context 'when the providers list is empty' do
114
- let(:configured_providers) { {} }
115
-
116
- it 'accepts nil' do
117
- provider_collection.default = nil
118
- expect(provider_collection.default).to be_nil
119
- end
120
-
121
- # rubocop:disable RSpec/MultipleExpectations
122
- it 'raises an ArgumentError for any other provider' do
123
- expect do
124
- provider_collection.default = other_provider
125
- end.to raise_error ArgumentError
126
- expect(provider_collection.default).to be_nil
127
- end
128
- # rubocop:enable RSpec/MultipleExpectations
129
- end
130
- end
131
-
132
- describe '#resolve' do
133
- context 'when the file extension is one of the providers' do
134
- [
135
- ['hola.one', :first_provider],
136
- ['hola.two', :second_provider],
137
- ].each do |test_params|
138
- filepath, provider = test_params
139
-
140
- it 'returns the corresponding provider' do
141
- provider_instance = public_send provider
142
- expect(provider_collection.resolve filepath).to eq provider_instance
143
- end
144
- end
145
- end
146
-
147
- context 'when the file extension is not one of the providers' do
148
- %w(hola.unknown hola).each do |filepath|
149
- it 'returns the default provider' do
150
- expect(provider_collection.resolve filepath).to eq first_provider
151
- end
152
- end
153
- end
154
- end
155
-
156
- describe '#reset' do
157
- let(:configured_default) { second_provider }
158
- let :provider do
159
- instance_double 'Rambling::Trie::Serializers::Marshal', :provider
160
- end
161
-
162
- before do
163
- provider_collection.add :three, provider
164
- provider_collection.default = provider
165
- end
166
-
167
- it 'resets to back to the initially configured values (:three => nil)' do
168
- provider_collection.reset
169
- expect(provider_collection[:three]).to be_nil
170
- end
171
-
172
- it 'resets to back to the initially configured default' do
173
- provider_collection.reset
174
- expect(provider_collection.default).to eq second_provider
175
- end
176
- end
177
- end