LittleWeasel 3.0.4 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (152) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +3 -0
  3. data/.reek.yml +17 -0
  4. data/.rspec +4 -2
  5. data/.rubocop.yml +187 -0
  6. data/.ruby-version +1 -1
  7. data/.yardopts +2 -0
  8. data/Gemfile +3 -1
  9. data/LittleWeasel.gemspec +31 -18
  10. data/README.md +408 -42
  11. data/Rakefile +296 -3
  12. data/lib/LittleWeasel.rb +5 -184
  13. data/lib/LittleWeasel/block_results.rb +81 -0
  14. data/lib/LittleWeasel/configure.rb +98 -0
  15. data/lib/LittleWeasel/dictionary.rb +125 -0
  16. data/lib/LittleWeasel/dictionary_key.rb +48 -0
  17. data/lib/LittleWeasel/dictionary_manager.rb +85 -0
  18. data/lib/LittleWeasel/errors/dictionary_file_already_loaded_error.rb +9 -0
  19. data/lib/LittleWeasel/errors/dictionary_file_empty_error.rb +8 -0
  20. data/lib/LittleWeasel/errors/dictionary_file_not_found_error.rb +8 -0
  21. data/lib/LittleWeasel/errors/dictionary_file_too_large_error.rb +16 -0
  22. data/lib/LittleWeasel/errors/language_required_error.rb +8 -0
  23. data/lib/LittleWeasel/errors/must_override_error.rb +8 -0
  24. data/lib/LittleWeasel/filters/en_us/currency_filter.rb +19 -0
  25. data/lib/LittleWeasel/filters/en_us/numeric_filter.rb +19 -0
  26. data/lib/LittleWeasel/filters/en_us/single_character_word_filter.rb +21 -0
  27. data/lib/LittleWeasel/filters/word_filter.rb +59 -0
  28. data/lib/LittleWeasel/filters/word_filter_managable.rb +80 -0
  29. data/lib/LittleWeasel/filters/word_filter_validatable.rb +31 -0
  30. data/lib/LittleWeasel/filters/word_filterable.rb +19 -0
  31. data/lib/LittleWeasel/filters/word_filters_validatable.rb +29 -0
  32. data/lib/LittleWeasel/metadata/dictionary_metadata.rb +145 -0
  33. data/lib/LittleWeasel/metadata/invalid_words_metadata.rb +134 -0
  34. data/lib/LittleWeasel/metadata/invalid_words_service_results.rb +45 -0
  35. data/lib/LittleWeasel/metadata/metadata_observable_validatable.rb +22 -0
  36. data/lib/LittleWeasel/metadata/metadata_observerable.rb +90 -0
  37. data/lib/LittleWeasel/metadata/metadatable.rb +136 -0
  38. data/lib/LittleWeasel/modules/class_name_to_symbol.rb +26 -0
  39. data/lib/LittleWeasel/modules/configurable.rb +26 -0
  40. data/lib/LittleWeasel/modules/deep_dup.rb +11 -0
  41. data/lib/LittleWeasel/modules/dictionary_cache_keys.rb +34 -0
  42. data/lib/LittleWeasel/modules/dictionary_cache_servicable.rb +26 -0
  43. data/lib/LittleWeasel/modules/dictionary_cache_validatable.rb +20 -0
  44. data/lib/LittleWeasel/modules/dictionary_creator_servicable.rb +27 -0
  45. data/lib/LittleWeasel/modules/dictionary_file_loader.rb +67 -0
  46. data/lib/LittleWeasel/modules/dictionary_key_validatable.rb +19 -0
  47. data/lib/LittleWeasel/modules/dictionary_keyable.rb +24 -0
  48. data/lib/LittleWeasel/modules/dictionary_loader_servicable.rb +27 -0
  49. data/lib/LittleWeasel/modules/dictionary_metadata_servicable.rb +29 -0
  50. data/lib/LittleWeasel/modules/dictionary_metadata_validatable.rb +17 -0
  51. data/lib/LittleWeasel/modules/dictionary_sourceable.rb +26 -0
  52. data/lib/LittleWeasel/modules/dictionary_validatable.rb +30 -0
  53. data/lib/LittleWeasel/modules/language.rb +23 -0
  54. data/lib/LittleWeasel/modules/language_validatable.rb +16 -0
  55. data/lib/LittleWeasel/modules/locale.rb +40 -0
  56. data/lib/LittleWeasel/modules/order_validatable.rb +18 -0
  57. data/lib/LittleWeasel/modules/orderable.rb +17 -0
  58. data/lib/LittleWeasel/modules/region.rb +23 -0
  59. data/lib/LittleWeasel/modules/region_validatable.rb +16 -0
  60. data/lib/LittleWeasel/modules/tag_validatable.rb +16 -0
  61. data/lib/LittleWeasel/modules/taggable.rb +31 -0
  62. data/lib/LittleWeasel/modules/word_results_validatable.rb +28 -0
  63. data/lib/LittleWeasel/preprocessors/en_us/capitalize_preprocessor.rb +22 -0
  64. data/lib/LittleWeasel/preprocessors/preprocessed_word.rb +28 -0
  65. data/lib/LittleWeasel/preprocessors/preprocessed_word_validatable.rb +55 -0
  66. data/lib/LittleWeasel/preprocessors/preprocessed_words.rb +55 -0
  67. data/lib/LittleWeasel/preprocessors/preprocessed_words_validatable.rb +27 -0
  68. data/lib/LittleWeasel/preprocessors/word_preprocessable.rb +19 -0
  69. data/lib/LittleWeasel/preprocessors/word_preprocessor.rb +122 -0
  70. data/lib/LittleWeasel/preprocessors/word_preprocessor_managable.rb +114 -0
  71. data/lib/LittleWeasel/preprocessors/word_preprocessor_validatable.rb +40 -0
  72. data/lib/LittleWeasel/preprocessors/word_preprocessors_validatable.rb +24 -0
  73. data/lib/LittleWeasel/services/dictionary_cache_service.rb +262 -0
  74. data/lib/LittleWeasel/services/dictionary_creator_service.rb +94 -0
  75. data/lib/LittleWeasel/services/dictionary_file_loader_service.rb +37 -0
  76. data/lib/LittleWeasel/services/dictionary_killer_service.rb +35 -0
  77. data/lib/LittleWeasel/services/dictionary_loader_service.rb +59 -0
  78. data/lib/LittleWeasel/services/dictionary_metadata_service.rb +114 -0
  79. data/lib/LittleWeasel/services/invalid_words_service.rb +59 -0
  80. data/lib/LittleWeasel/version.rb +3 -1
  81. data/lib/LittleWeasel/word_results.rb +146 -0
  82. data/spec/factories/dictionary.rb +43 -0
  83. data/spec/factories/dictionary_cache_service.rb +95 -0
  84. data/spec/factories/dictionary_creator_service.rb +16 -0
  85. data/spec/factories/dictionary_file_loader_service.rb +13 -0
  86. data/spec/factories/dictionary_hash.rb +39 -0
  87. data/spec/factories/dictionary_key.rb +14 -0
  88. data/spec/factories/dictionary_killer_service.rb +14 -0
  89. data/spec/factories/dictionary_loader_service.rb +14 -0
  90. data/spec/factories/dictionary_manager.rb +10 -0
  91. data/spec/factories/dictionary_metadata.rb +16 -0
  92. data/spec/factories/dictionary_metadata_service.rb +16 -0
  93. data/spec/factories/numeric_filter.rb +12 -0
  94. data/spec/factories/preprocessed_word.rb +16 -0
  95. data/spec/factories/preprocessed_words.rb +41 -0
  96. data/spec/factories/single_character_word_filter.rb +12 -0
  97. data/spec/factories/word_results.rb +16 -0
  98. data/spec/lib/LittleWeasel/block_results_spec.rb +248 -0
  99. data/spec/lib/LittleWeasel/configure_spec.rb +74 -0
  100. data/spec/lib/LittleWeasel/dictionary_key_spec.rb +118 -0
  101. data/spec/lib/LittleWeasel/dictionary_manager_spec.rb +116 -0
  102. data/spec/lib/LittleWeasel/dictionary_spec.rb +289 -0
  103. data/spec/lib/LittleWeasel/filters/en_us/currency_filter_spec.rb +80 -0
  104. data/spec/lib/LittleWeasel/filters/en_us/numeric_filter_spec.rb +66 -0
  105. data/spec/lib/LittleWeasel/filters/en_us/single_character_word_filter_spec.rb +58 -0
  106. data/spec/lib/LittleWeasel/filters/word_filter_managable_spec.rb +180 -0
  107. data/spec/lib/LittleWeasel/filters/word_filter_spec.rb +151 -0
  108. data/spec/lib/LittleWeasel/filters/word_filter_validatable_spec.rb +94 -0
  109. data/spec/lib/LittleWeasel/filters/word_filters_validatable_spec.rb +48 -0
  110. data/spec/lib/LittleWeasel/integraton_tests/dictionary_integration_spec.rb +201 -0
  111. data/spec/lib/LittleWeasel/metadata/dictionary_creator_servicable_spec.rb +54 -0
  112. data/spec/lib/LittleWeasel/metadata/dictionary_metadata_spec.rb +209 -0
  113. data/spec/lib/LittleWeasel/metadata/invalid_words_metadata_spec.rb +155 -0
  114. data/spec/lib/LittleWeasel/metadata/metadata_observerable_spec.rb +31 -0
  115. data/spec/lib/LittleWeasel/metadata/metadatable_spec.rb +35 -0
  116. data/spec/lib/LittleWeasel/modules/class_name_to_symbol_spec.rb +21 -0
  117. data/spec/lib/LittleWeasel/modules/dictionary_file_loader_spec.rb +125 -0
  118. data/spec/lib/LittleWeasel/modules/dictionary_sourceable_spec.rb +44 -0
  119. data/spec/lib/LittleWeasel/modules/language_spec.rb +52 -0
  120. data/spec/lib/LittleWeasel/modules/locale_spec.rb +140 -0
  121. data/spec/lib/LittleWeasel/modules/region_spec.rb +52 -0
  122. data/spec/lib/LittleWeasel/preprocessors/en_us/capitalize_preprocessor_spec.rb +34 -0
  123. data/spec/lib/LittleWeasel/preprocessors/preprocessed_word_spec.rb +105 -0
  124. data/spec/lib/LittleWeasel/preprocessors/preprocessed_word_validatable_spec.rb +143 -0
  125. data/spec/lib/LittleWeasel/preprocessors/preprocessed_words_spec.rb +77 -0
  126. data/spec/lib/LittleWeasel/preprocessors/preprocessed_words_validatable_spec.rb +58 -0
  127. data/spec/lib/LittleWeasel/preprocessors/word_preprocessor_managable_spec.rb +216 -0
  128. data/spec/lib/LittleWeasel/preprocessors/word_preprocessor_spec.rb +175 -0
  129. data/spec/lib/LittleWeasel/preprocessors/word_preprocessor_validatable_spec.rb +109 -0
  130. data/spec/lib/LittleWeasel/preprocessors/word_preprocessors_validatable_spec.rb +49 -0
  131. data/spec/lib/LittleWeasel/services/dictionary_cache_service_spec.rb +444 -0
  132. data/spec/lib/LittleWeasel/services/dictionary_creator_service_spec.rb +119 -0
  133. data/spec/lib/LittleWeasel/services/dictionary_file_loader_service_spec.rb +71 -0
  134. data/spec/lib/LittleWeasel/services/dictionary_loader_service_spec.rb +50 -0
  135. data/spec/lib/LittleWeasel/services/dictionary_metadata_service_spec.rb +279 -0
  136. data/spec/lib/LittleWeasel/word_results_spec.rb +275 -0
  137. data/spec/lib/LittleWeasel/workflow/workflow_spec.rb +20 -0
  138. data/spec/spec_helper.rb +117 -6
  139. data/spec/support/factory_bot.rb +15 -0
  140. data/spec/support/file_helpers.rb +32 -0
  141. data/spec/support/files/empty-dictionary.txt +0 -0
  142. data/{lib/dictionary → spec/support/files/en-US-big.txt} +262156 -31488
  143. data/spec/support/files/en-US-tagged.txt +26 -0
  144. data/spec/support/files/en-US.txt +26 -0
  145. data/spec/support/files/en.txt +26 -0
  146. data/spec/support/files/es-ES.txt +27 -0
  147. data/spec/support/files/es.txt +27 -0
  148. data/spec/support/general_helpers.rb +68 -0
  149. data/spec/support/shared_contexts.rb +108 -0
  150. data/spec/support/shared_examples.rb +105 -0
  151. metadata +408 -65
  152. data/spec/checker/checker_spec.rb +0 -286
data/Rakefile CHANGED
@@ -1,13 +1,306 @@
1
- require "bundler/gem_tasks"
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/core_ext/object/try.rb'
4
+ require 'active_support/inflector'
5
+ require 'benchmark/ips'
6
+ require 'bundler/gem_tasks'
7
+ require 'pry'
8
+
9
+ require_relative 'lib/LittleWeasel'
10
+ require_relative 'spec/support/file_helpers'
11
+ require_relative 'spec/support/general_helpers'
12
+
13
+ DictionaryResultsHelpers = Support::GeneralHelpers::DictionaryResultsHelpers
14
+
15
+ def file_from(dictionary_key)
16
+ Support::FileHelpers.dictionary_path_for(file_name: dictionary_key.key)
17
+ end
2
18
 
3
19
  begin
4
20
  require 'rspec/core/rake_task'
5
21
  RSpec::Core::RakeTask.new(:spec)
6
22
  rescue LoadError => e
7
- task "spec" do
23
+ task 'spec' do
8
24
  puts "RSpec not loaded - make sure it's installed and you're using bundle exec"
9
25
  exit 1
10
26
  end
11
27
  end
12
28
 
13
- task :default => :spec
29
+ #
30
+ # Tasks related to the #word_results API
31
+
32
+ namespace 'word_results' do
33
+ # Creates a dictionary from a file on disk
34
+ task :basic do
35
+ LittleWeasel.configure do |config|
36
+ # TODO: Configure as needed here.
37
+ end
38
+
39
+ # Create a Dictionary Manager.
40
+ dictionary_manager = LittleWeasel::DictionaryManager.new
41
+
42
+ # Create our unique key for the dictionary.
43
+ en_us_key = LittleWeasel::DictionaryKey.new(language: :en, region: :us)
44
+
45
+ file = Support::FileHelpers.dictionary_path_for file_name: en_us_key.key
46
+
47
+ # Create a dictionary of names from memory.
48
+ en_us_names_dictionary = dictionary_manager.create_dictionary_from_file(
49
+ dictionary_key: en_us_key,
50
+ file: file)
51
+
52
+ # Get some word results...
53
+
54
+ # Get results for a word we know exists.
55
+ word = 'apple'
56
+ word_results = en_us_names_dictionary.word_results word
57
+ DictionaryResultsHelpers.print_word_results word, word_results, "found (#{word} is in the dictionary)"
58
+
59
+ # Get results for a word we know DOES NOT exist.
60
+ word = 'dapple'
61
+ word_results = en_us_names_dictionary.word_results word
62
+ DictionaryResultsHelpers.print_word_results word, word_results, "not found (#{word} is not in the dictionary)"
63
+ rescue StandardError => e
64
+ task 'word_results:basic' do
65
+ puts "LittleWeasel task word_results:basic not loaded: #{e.message}"
66
+ exit 1
67
+ end
68
+ end
69
+
70
+ # Creates a dictionary of names from memory
71
+ task :from_memory do
72
+ LittleWeasel.configure do |config|
73
+ # TODO: Configure as needed here.
74
+ end
75
+
76
+ # Create a Dictionary Manager.
77
+ dictionary_manager = LittleWeasel::DictionaryManager.new
78
+
79
+ # Create our unique key for the dictionary.
80
+ en_us_names_key = LittleWeasel::DictionaryKey.new(language: :en, region: :us, tag: :names)
81
+
82
+ # Create a dictionary of names from memory.
83
+ en_us_names_dictionary = dictionary_manager.create_dictionary_from_memory(
84
+ dictionary_key: en_us_names_key, dictionary_words: %w(Abel Bartholomew Cain Deborah Elijah))
85
+
86
+ # Get some word results...
87
+
88
+ # Get results for a name we know exists.
89
+ word = 'Abel'
90
+ word_results = en_us_names_dictionary.word_results word
91
+ DictionaryResultsHelpers.print_word_results word, word_results, "found (#{word} is in the dictionary)"
92
+
93
+ # Get results for a name we know DOES NOT exist.
94
+ word = 'Henry'
95
+ word_results = en_us_names_dictionary.word_results word
96
+ DictionaryResultsHelpers.print_word_results word, word_results, "not found (#{word} is not in the dictionary)"
97
+ rescue StandardError => e
98
+ task 'word_results:from_memory' do
99
+ puts "LittleWeasel task word_results:from_memory not loaded: #{e.message}"
100
+ exit 1
101
+ end
102
+ end
103
+
104
+ # Shows application of word filters and word preprocessors.
105
+ task :advanced do
106
+ LittleWeasel.configure do |config|
107
+ # TODO: Configure as needed here.
108
+ end
109
+
110
+ # Create a Dictionary Manager.
111
+ dictionary_manager = LittleWeasel::DictionaryManager.new
112
+
113
+ # Create our unique key for the dictionary.
114
+ en_us_names_key = LittleWeasel::DictionaryKey.new(language: :en, region: :us, tag: :names)
115
+
116
+ # Create a Henry word filter.
117
+ class HenryFilter < LittleWeasel::Filters::WordFilter
118
+ class << self
119
+ def filter_match?(word)
120
+ word== 'Henry'
121
+ end
122
+ end
123
+ end
124
+ word_filters = [HenryFilter.new]
125
+
126
+ # Add a word preprocessor.
127
+ word_preprocessors = [LittleWeasel::Preprocessors::EnUs::CapitalizePreprocessor.new]
128
+
129
+ # Create a dictionary of names from memory.
130
+ en_us_names_dictionary = dictionary_manager.create_dictionary_from_memory(
131
+ dictionary_key: en_us_names_key,
132
+ dictionary_words: %w(Abel Bartholomew Cain Deborah Elijah),
133
+ word_filters: word_filters,
134
+ word_preprocessors: word_preprocessors)
135
+
136
+ puts '# Turning off our word filters and word preprocessors to start...'
137
+ puts
138
+
139
+ en_us_names_dictionary.filters_on = false
140
+ en_us_names_dictionary.preprocessors_on = false
141
+
142
+ # Get results for a name we know DOES NOT exist.
143
+ word = 'Henry'
144
+ word_results = en_us_names_dictionary.word_results word
145
+ DictionaryResultsHelpers.print_word_results word, word_results, "not found, #success? == false, word_valid? == false (#{word} is not in the dictionary)"
146
+
147
+ puts '# Turning word filters on...'
148
+ puts
149
+
150
+ en_us_names_dictionary.filters_on = true
151
+
152
+ # Get results for Henry again - it should be found due to the filter.
153
+ word = 'Henry'
154
+ word_results = en_us_names_dictionary.word_results word
155
+ DictionaryResultsHelpers.print_word_results word, word_results, '#success? == true due to the HenryFilter'
156
+
157
+ # Get results for a name we know DOES NOT exist.
158
+ word = 'henry'
159
+ word_results = en_us_names_dictionary.word_results word
160
+ DictionaryResultsHelpers.print_word_results word, word_results, "not found, #success? == false (#{word} is not in the dictionary and henry is lower case, no filter match)"
161
+
162
+ puts '# Turning preprocessors on so that henry is converted to Henry '
163
+ puts "# and consequently, the filter will match..."
164
+ puts
165
+
166
+ en_us_names_dictionary.preprocessors_on = true
167
+
168
+ word = 'henry'
169
+ word_results = en_us_names_dictionary.word_results word
170
+ DictionaryResultsHelpers.print_word_results word, word_results, "#success? == true, #filter_match? == true (#{word} is not in the dictionary but the word preprocessor and word filter work together to get a filter match and consider the name valid)"
171
+ rescue StandardError => e
172
+ task 'word_results:advanced' do
173
+ puts "LittleWeasel task word_results:advanced not loaded: #{e.message}"
174
+ exit 1
175
+ end
176
+ end
177
+
178
+ task :word_filters do
179
+ LittleWeasel.configure do |config|
180
+ # TODO: Configure as needed here.
181
+ end
182
+ dictionary_manager = LittleWeasel::DictionaryManager.new
183
+ dictionary_key = LittleWeasel::DictionaryKey.new(language: :en, region: :us)
184
+ file = Support::FileHelpers.dictionary_path_for file_name: dictionary_key.key
185
+ word_filters = [
186
+ LittleWeasel::Filters::EnUs::NumericFilter.new,
187
+ LittleWeasel::Filters::EnUs::CurrencyFilter.new,
188
+ LittleWeasel::Filters::EnUs::SingleCharacterWordFilter.new
189
+ ]
190
+ word_preprocessors = nil
191
+ dictionary_words = Support::FileHelpers.dictionary_words_for dictionary_file_path: file
192
+ dictionary = dictionary_manager.create_dictionary_from_memory(dictionary_key: dictionary_key, dictionary_words: dictionary_words, word_filters: word_filters, word_preprocessors: word_preprocessors)
193
+ dictionary_words << 'A'.dup
194
+ dictionary_words << 'I'.dup
195
+ dictionary_words << '1000'.dup
196
+ dictionary_words << '1,000'.dup
197
+ dictionary_words << '10,000.00'.dup
198
+ dictionary_words << '+100.00'.dup
199
+ dictionary_words << '-200,000.00'.dup
200
+ dictionary_words << '$100,000'.dup
201
+ dictionary_words << '+$100,000,000.10'.dup
202
+ dictionary_words << '-$999,000,000.10'.dup
203
+ dictionary_words.each do |word|
204
+ word.strip!
205
+ word_results = dictionary.word_results word
206
+ DictionaryResultsHelpers.print_word_results word, word_results
207
+ end
208
+ rescue StandardError => e
209
+ task 'word_results:word_filters' do
210
+ puts "LittleWeasel task word_results:word_filters not loaded: #{e.message}"
211
+ exit 1
212
+ end
213
+ end
214
+ end
215
+
216
+ #
217
+ # Tasks related to the #block_results API
218
+
219
+ namespace 'block_results' do
220
+ task :basic do
221
+ LittleWeasel.configure do |config|
222
+ # TODO: Configure as needed here.
223
+ end
224
+
225
+ # Create a Dictionary Manager.
226
+ dictionary_manager = LittleWeasel::DictionaryManager.new
227
+
228
+ # Create our unique key for the dictionary.
229
+ en_us_key = LittleWeasel::DictionaryKey.new(language: :en, region: :us, tag: :big)
230
+
231
+ # Create a dictionary from a file on disk. The below assumes the
232
+ # dictionary file name matches the dictionary key (e.g. en-US-big).
233
+ en_us_dictionary = dictionary_manager.create_dictionary_from_file(
234
+ dictionary_key: en_us_key, file: file_from(en_us_key))
235
+
236
+ word_block = "This is a word-block of 8 words and 2 numbers."
237
+
238
+ # Add a word filter so that numbers are considered valid.
239
+ en_us_dictionary.add_filters word_filters: [
240
+ LittleWeasel::Filters::EnUs::NumericFilter.new
241
+ ]
242
+
243
+ block_results = en_us_dictionary.block_results word_block
244
+
245
+ # Returns a LittleWeasel::BlockResults object.
246
+ DictionaryResultsHelpers.print_block_results word_block, block_results
247
+ rescue StandardError => e
248
+ task 'block_results:basic' do
249
+ puts "LittleWeasel task block_results:basic not loaded: #{e.message}"
250
+ exit 1
251
+ end
252
+ end
253
+ end
254
+
255
+ namespace :bm do
256
+ task :hash do
257
+ STRING_LOCALE = { 'en-US' => 'en-us' }
258
+ SYMBOL_LOCALE = { 'en-US' => :enUS }
259
+
260
+ puts 'String variable vs. normal String.'
261
+ Benchmark.ips do |x|
262
+ string_variable = 'string_variable'
263
+ x.report('string variable') { STRING_LOCALE[string_variable] }
264
+ x.report('normal') { STRING_LOCALE['en-US'] }
265
+ end
266
+
267
+ puts 'String#freeze vs. normal String.'
268
+ Benchmark.ips do |x|
269
+ x.report('freeze') { STRING_LOCALE['en-US'.freeze] }
270
+ x.report('normal') { STRING_LOCALE['en-US'] }
271
+ end
272
+
273
+ puts 'String vs Symbol'
274
+ Benchmark.ips do |x|
275
+ x.report('string') { STRING_LOCALE['en-US'] }
276
+ x.report('symbol') { SYMBOL_LOCALE[:enUS] }
277
+ end
278
+
279
+ puts 'String#freeze vs. Symbol'
280
+ Benchmark.ips do |x|
281
+ x.report('string') { STRING_LOCALE['en-US'.freeze] }
282
+ x.report('symbol') { SYMBOL_LOCALE[:enUS] }
283
+ end
284
+ rescue StandardError => e
285
+ task 'hash' do
286
+ puts "LittleWeasel task bm:hash not loaded: #{e.message}"
287
+ exit 1
288
+ end
289
+ end
290
+
291
+ task :dictionary_key do
292
+ puts 'DictionaryKey test'
293
+ Benchmark.ips do |x|
294
+ x.report('DictionaryKey') do
295
+ DictionaryKey.key(language: :en, region: :us, tag: :tag)
296
+ end
297
+ end
298
+ rescue StandardError => e
299
+ task 'locale' do
300
+ puts "LittleWeasel task bm:dictionary_key not loaded: #{e.message}"
301
+ exit 1
302
+ end
303
+ end
304
+ end
305
+
306
+ task default: :spec
data/lib/LittleWeasel.rb CHANGED
@@ -1,186 +1,7 @@
1
- require 'singleton'
2
- require "LittleWeasel/version"
3
- require 'active_support/inflector'
1
+ # frozen_string_literal: true
4
2
 
5
- module LittleWeasel
3
+ require 'active_support/core_ext/object/blank'
6
4
 
7
- # Provides methods to interrogate the dictionary.
8
- class Checker
9
- include Singleton
10
-
11
- # Returns the dictionary.
12
- #
13
- # @return [Hash] the dictionary.
14
- attr_reader :dictionary
15
-
16
- private
17
-
18
- attr_reader :alphabet_exclusion_list
19
-
20
- # Keep these private...will expose as options later.
21
- attr_accessor :word_regex, :numeric_regex, :non_wordchar_regex
22
-
23
- public
24
-
25
- # The constructor
26
- def initialize
27
- @options = { exclude_alphabet: false, strip_whitespace: false, ignore_numeric: true, single_word_mode: false }
28
- @alphabet_exclusion_list = %w{ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z }
29
- @numeric_regex = /^[-+]?[0-9]?(\.[0-9]+)?$+/
30
- @word_regex = /\s+(?=(?:[^"]*"[^"]*")*[^"]*$)/
31
- @non_wordchar_regex = /\W+/
32
- @dictionary = Hash.new(1)
33
- load
34
- end
35
-
36
- # Interrogates the dictionary to determine whether or not [word] exists.
37
- #
38
- # @param [String] word the word or words to interrogate
39
- # @param [Hash] options options to apply to this query (see #options=). Options passed to this
40
- # method are applied for this query only.
41
- #
42
- # @return [Boolean] true if the word/words in *word* exists, false otherwise.
43
- #
44
- # @example
45
- #
46
- # LittleWeasel::Checker.instance.exists?('C') # true (default options, :exclude_alphabet => false)
47
- # LittleWeasel::Checker.instance.exists?('A', {exclude_alphabet:true}) # false
48
- # LittleWeasel::Checker.instance.exists?('X', {exclude_alphabet:false}) # true
49
- # LittleWeasel::Checker.instance.exists?('Hello') # true
50
- #
51
- # LittleWeasel::Checker.instance.exists?(' Hello ') # false (default options, :strip_whitespace => false)
52
- # LittleWeasel::Checker.instance.exists?(' Yes ', {strip_whitespace:true}) # true
53
- # LittleWeasel::Checker.instance.exists?('No ', {strip_whitespace:false}) # false
54
- # LittleWeasel::Checker.instance.exists?('How dy', {strip_whitespace:true}) # false, strip_whitespace only removes leading and trailing spaces
55
- #
56
- # LittleWeasel::Checker.instance.exists?('90210') # true (default options, ignore_numeric => true)
57
- # LittleWeasel::Checker.instance.exists?('90210', {ignore_numeric:false}) # false
58
- #
59
- # LittleWeasel::Checker.instance.exists?('Hello World') # true, we're accepting multiple words now by default (default options, single_word_mode => false) :)
60
- # LittleWeasel::Checker.instance.exists?("hello, mister; did I \'mention\'' that lemon cake is \"great?\" It's just wonderful!") # true
61
- #
62
- # LittleWeasel::Checker.instance.exists?('I love ice cream', {single_word_mode:true}) # false; while all the words are valid, more than one word will return false
63
- #
64
- def exists?(word, options=nil)
65
- options = options || @options
66
-
67
- return false unless word.is_a?(String)
68
-
69
- word = word.dup
70
- word.strip! if options[:strip_whitespace]
71
-
72
- return false if word.empty?
73
-
74
- if block? word
75
- return false if options[:single_word_mode]
76
- return block_exists? word
77
- end
78
-
79
- return true if options[:ignore_numeric] && number?(word)
80
- return false if options[:exclude_alphabet] && word.length == 1 && @alphabet_exclusion_list.include?(word.upcase)
81
-
82
- valid_word? word
83
- end
84
-
85
- # Sets the global options for this gem.
86
- #
87
- # @param [Hash] options options that should apply to all subsequent calls to method *exists?* (see #exists?).
88
- # Options set via this property apply to all subsequent queries.
89
- #
90
- # @option options [Boolean] :exclude_alphabet (false) If false, letters of the alphabet are considered words.
91
- # @option options [Boolean] :strip_whitespace (false) If true, leading and trailing spaces are removed before checking to see if the word exists.
92
- # @option options [Boolean] :ignore_numeric (true) If true, numeric values are considered valid words.
93
- # @option options [Boolean] :single_word_mode (false) If false, word blocks (more than one word) are considered valid if all the words exist in the dictionary.
94
- #
95
- # @return [Hash] The options
96
- #
97
- # @example
98
- # LittleWeasel::Checker.instance.options({exclude_alphabet:true})
99
- # LittleWeasel::Checker.instance.exists?('A') # false
100
- #
101
- # LittleWeasel::Checker.instance.options({exclude_alphabet:false})
102
- # LittleWeasel::Checker.instance.exists?('A') # true
103
- #
104
- # LittleWeasel::Checker.instance.options({strip_whitespace:false})
105
- # LittleWeasel::Checker.instance.exists?(' Hello ') # false
106
- # LittleWeasel::Checker.instance.exists?('No ') # false
107
- # LittleWeasel::Checker.instance.exists?(' No') # false
108
- #
109
- # LittleWeasel::Checker.instance.options({strip_whitespace:true})
110
- # LittleWeasel::Checker.instance.exists?(' Yes ') # true
111
- # LittleWeasel::Checker.instance.exists?('How dy') # false, strip_whitespace only removes leading and trailing spaces
112
- #
113
- # LittleWeasel::Checker.instance.exists?('90210') # true (default options, ignore_numeric => true)
114
- # LittleWeasel::Checker.instance.exists?('90210', {ignore_numeric:false}) # false
115
- # LittleWeasel::Checker.instance.exists?('I watch Beverly Hills 90210') # true (default options, ignore_numeric => true)
116
- # LittleWeasel::Checker.instance.exists?('I watch Beverly Hills 90210', {ignore_numeric:false}) # false
117
- #
118
- # LittleWeasel::Checker.instance.options({single_word_mode:true})
119
- # LittleWeasel::Checker.instance.exists?('I love ice cream') # false; while all the words are valid, more than one word will return false
120
- # LittleWeasel::Checker.instance.exists?('Baby') # true
121
- #
122
- def options=(options)
123
- @options = options
124
- end
125
-
126
- # Gets the global options currently set for this gem.
127
- #
128
- # @return [Hash] The options
129
- def options
130
- @options
131
- end
132
-
133
- protected
134
-
135
- def number?(word)
136
- word.strip.gsub(@numeric_regex).count > 0
137
- end
138
-
139
- def block?(string)
140
- string = string.dup
141
- return false unless string.is_a?(String)
142
- string.gsub!(@numeric_regex, "")
143
- return false unless string.length > 1
144
- string.strip.scan(/[\w'-]+/).length > 1
145
- end
146
-
147
- def block_exists?(word_block)
148
- word_block = word_block.dup
149
-
150
- word_block.gsub!(@numeric_regex, "") if options[:ignore_numeric]
151
- return false if word_block.nil?
152
- word_block.strip! unless word_block.nil?
153
- word_block.gsub!(@non_wordchar_regex, " ")
154
- word_block.split(@word_regex).uniq.each { |word|
155
- return false unless valid_block_word?(word)
156
- }
157
- return true
158
- end
159
-
160
- def valid_word?(word)
161
- word = word.dup.downcase
162
- exists = dictionary.has_key?(word)
163
- exists = dictionary.has_key?(word.singularize) unless exists
164
- exists
165
- end
166
-
167
- def valid_block_word?(word)
168
- return true if word.length == 1
169
- valid_word? word.strip
170
- end
171
-
172
- private
173
-
174
- def dictionary_path
175
- File.expand_path(File.dirname(__FILE__) + '/dictionary')
176
- end
177
-
178
- def load
179
- File.open(dictionary_path) do |io|
180
- io.each { |line| line.chomp!; @dictionary[line] = line }
181
- end
182
- end
183
-
184
- end
185
-
186
- end
5
+ Dir[File.join('.', 'lib/LittleWeasel/**/*.rb')].each do |f|
6
+ require f
7
+ end