LittleWeasel 3.0.4 → 4.0.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.
- checksums.yaml +5 -5
- data/.gitignore +3 -0
- data/.reek.yml +17 -0
- data/.rspec +4 -2
- data/.rubocop.yml +187 -0
- data/.ruby-version +1 -1
- data/.yardopts +2 -0
- data/Gemfile +3 -1
- data/LittleWeasel.gemspec +31 -18
- data/README.md +408 -42
- data/Rakefile +296 -3
- data/lib/LittleWeasel.rb +5 -184
- data/lib/LittleWeasel/block_results.rb +81 -0
- data/lib/LittleWeasel/configure.rb +98 -0
- data/lib/LittleWeasel/dictionary.rb +125 -0
- data/lib/LittleWeasel/dictionary_key.rb +48 -0
- data/lib/LittleWeasel/dictionary_manager.rb +85 -0
- data/lib/LittleWeasel/errors/dictionary_file_already_loaded_error.rb +9 -0
- data/lib/LittleWeasel/errors/dictionary_file_empty_error.rb +8 -0
- data/lib/LittleWeasel/errors/dictionary_file_not_found_error.rb +8 -0
- data/lib/LittleWeasel/errors/dictionary_file_too_large_error.rb +16 -0
- data/lib/LittleWeasel/errors/language_required_error.rb +8 -0
- data/lib/LittleWeasel/errors/must_override_error.rb +8 -0
- data/lib/LittleWeasel/filters/en_us/currency_filter.rb +19 -0
- data/lib/LittleWeasel/filters/en_us/numeric_filter.rb +19 -0
- data/lib/LittleWeasel/filters/en_us/single_character_word_filter.rb +21 -0
- data/lib/LittleWeasel/filters/word_filter.rb +59 -0
- data/lib/LittleWeasel/filters/word_filter_managable.rb +80 -0
- data/lib/LittleWeasel/filters/word_filter_validatable.rb +31 -0
- data/lib/LittleWeasel/filters/word_filterable.rb +19 -0
- data/lib/LittleWeasel/filters/word_filters_validatable.rb +29 -0
- data/lib/LittleWeasel/metadata/dictionary_metadata.rb +145 -0
- data/lib/LittleWeasel/metadata/invalid_words_metadata.rb +134 -0
- data/lib/LittleWeasel/metadata/invalid_words_service_results.rb +45 -0
- data/lib/LittleWeasel/metadata/metadata_observable_validatable.rb +22 -0
- data/lib/LittleWeasel/metadata/metadata_observerable.rb +90 -0
- data/lib/LittleWeasel/metadata/metadatable.rb +136 -0
- data/lib/LittleWeasel/modules/class_name_to_symbol.rb +26 -0
- data/lib/LittleWeasel/modules/configurable.rb +26 -0
- data/lib/LittleWeasel/modules/deep_dup.rb +11 -0
- data/lib/LittleWeasel/modules/dictionary_cache_keys.rb +34 -0
- data/lib/LittleWeasel/modules/dictionary_cache_servicable.rb +26 -0
- data/lib/LittleWeasel/modules/dictionary_cache_validatable.rb +20 -0
- data/lib/LittleWeasel/modules/dictionary_creator_servicable.rb +27 -0
- data/lib/LittleWeasel/modules/dictionary_file_loader.rb +67 -0
- data/lib/LittleWeasel/modules/dictionary_key_validatable.rb +19 -0
- data/lib/LittleWeasel/modules/dictionary_keyable.rb +24 -0
- data/lib/LittleWeasel/modules/dictionary_loader_servicable.rb +27 -0
- data/lib/LittleWeasel/modules/dictionary_metadata_servicable.rb +29 -0
- data/lib/LittleWeasel/modules/dictionary_metadata_validatable.rb +17 -0
- data/lib/LittleWeasel/modules/dictionary_sourceable.rb +26 -0
- data/lib/LittleWeasel/modules/dictionary_validatable.rb +30 -0
- data/lib/LittleWeasel/modules/language.rb +23 -0
- data/lib/LittleWeasel/modules/language_validatable.rb +16 -0
- data/lib/LittleWeasel/modules/locale.rb +40 -0
- data/lib/LittleWeasel/modules/order_validatable.rb +18 -0
- data/lib/LittleWeasel/modules/orderable.rb +17 -0
- data/lib/LittleWeasel/modules/region.rb +23 -0
- data/lib/LittleWeasel/modules/region_validatable.rb +16 -0
- data/lib/LittleWeasel/modules/tag_validatable.rb +16 -0
- data/lib/LittleWeasel/modules/taggable.rb +31 -0
- data/lib/LittleWeasel/modules/word_results_validatable.rb +28 -0
- data/lib/LittleWeasel/preprocessors/en_us/capitalize_preprocessor.rb +22 -0
- data/lib/LittleWeasel/preprocessors/preprocessed_word.rb +28 -0
- data/lib/LittleWeasel/preprocessors/preprocessed_word_validatable.rb +55 -0
- data/lib/LittleWeasel/preprocessors/preprocessed_words.rb +55 -0
- data/lib/LittleWeasel/preprocessors/preprocessed_words_validatable.rb +27 -0
- data/lib/LittleWeasel/preprocessors/word_preprocessable.rb +19 -0
- data/lib/LittleWeasel/preprocessors/word_preprocessor.rb +122 -0
- data/lib/LittleWeasel/preprocessors/word_preprocessor_managable.rb +114 -0
- data/lib/LittleWeasel/preprocessors/word_preprocessor_validatable.rb +40 -0
- data/lib/LittleWeasel/preprocessors/word_preprocessors_validatable.rb +24 -0
- data/lib/LittleWeasel/services/dictionary_cache_service.rb +262 -0
- data/lib/LittleWeasel/services/dictionary_creator_service.rb +94 -0
- data/lib/LittleWeasel/services/dictionary_file_loader_service.rb +37 -0
- data/lib/LittleWeasel/services/dictionary_killer_service.rb +35 -0
- data/lib/LittleWeasel/services/dictionary_loader_service.rb +59 -0
- data/lib/LittleWeasel/services/dictionary_metadata_service.rb +114 -0
- data/lib/LittleWeasel/services/invalid_words_service.rb +59 -0
- data/lib/LittleWeasel/version.rb +3 -1
- data/lib/LittleWeasel/word_results.rb +146 -0
- data/spec/factories/dictionary.rb +43 -0
- data/spec/factories/dictionary_cache_service.rb +95 -0
- data/spec/factories/dictionary_creator_service.rb +16 -0
- data/spec/factories/dictionary_file_loader_service.rb +13 -0
- data/spec/factories/dictionary_hash.rb +39 -0
- data/spec/factories/dictionary_key.rb +14 -0
- data/spec/factories/dictionary_killer_service.rb +14 -0
- data/spec/factories/dictionary_loader_service.rb +14 -0
- data/spec/factories/dictionary_manager.rb +10 -0
- data/spec/factories/dictionary_metadata.rb +16 -0
- data/spec/factories/dictionary_metadata_service.rb +16 -0
- data/spec/factories/numeric_filter.rb +12 -0
- data/spec/factories/preprocessed_word.rb +16 -0
- data/spec/factories/preprocessed_words.rb +41 -0
- data/spec/factories/single_character_word_filter.rb +12 -0
- data/spec/factories/word_results.rb +16 -0
- data/spec/lib/LittleWeasel/block_results_spec.rb +248 -0
- data/spec/lib/LittleWeasel/configure_spec.rb +74 -0
- data/spec/lib/LittleWeasel/dictionary_key_spec.rb +118 -0
- data/spec/lib/LittleWeasel/dictionary_manager_spec.rb +116 -0
- data/spec/lib/LittleWeasel/dictionary_spec.rb +289 -0
- data/spec/lib/LittleWeasel/filters/en_us/currency_filter_spec.rb +80 -0
- data/spec/lib/LittleWeasel/filters/en_us/numeric_filter_spec.rb +66 -0
- data/spec/lib/LittleWeasel/filters/en_us/single_character_word_filter_spec.rb +58 -0
- data/spec/lib/LittleWeasel/filters/word_filter_managable_spec.rb +180 -0
- data/spec/lib/LittleWeasel/filters/word_filter_spec.rb +151 -0
- data/spec/lib/LittleWeasel/filters/word_filter_validatable_spec.rb +94 -0
- data/spec/lib/LittleWeasel/filters/word_filters_validatable_spec.rb +48 -0
- data/spec/lib/LittleWeasel/integraton_tests/dictionary_integration_spec.rb +201 -0
- data/spec/lib/LittleWeasel/metadata/dictionary_creator_servicable_spec.rb +54 -0
- data/spec/lib/LittleWeasel/metadata/dictionary_metadata_spec.rb +209 -0
- data/spec/lib/LittleWeasel/metadata/invalid_words_metadata_spec.rb +155 -0
- data/spec/lib/LittleWeasel/metadata/metadata_observerable_spec.rb +31 -0
- data/spec/lib/LittleWeasel/metadata/metadatable_spec.rb +35 -0
- data/spec/lib/LittleWeasel/modules/class_name_to_symbol_spec.rb +21 -0
- data/spec/lib/LittleWeasel/modules/dictionary_file_loader_spec.rb +125 -0
- data/spec/lib/LittleWeasel/modules/dictionary_sourceable_spec.rb +44 -0
- data/spec/lib/LittleWeasel/modules/language_spec.rb +52 -0
- data/spec/lib/LittleWeasel/modules/locale_spec.rb +140 -0
- data/spec/lib/LittleWeasel/modules/region_spec.rb +52 -0
- data/spec/lib/LittleWeasel/preprocessors/en_us/capitalize_preprocessor_spec.rb +34 -0
- data/spec/lib/LittleWeasel/preprocessors/preprocessed_word_spec.rb +105 -0
- data/spec/lib/LittleWeasel/preprocessors/preprocessed_word_validatable_spec.rb +143 -0
- data/spec/lib/LittleWeasel/preprocessors/preprocessed_words_spec.rb +77 -0
- data/spec/lib/LittleWeasel/preprocessors/preprocessed_words_validatable_spec.rb +58 -0
- data/spec/lib/LittleWeasel/preprocessors/word_preprocessor_managable_spec.rb +216 -0
- data/spec/lib/LittleWeasel/preprocessors/word_preprocessor_spec.rb +175 -0
- data/spec/lib/LittleWeasel/preprocessors/word_preprocessor_validatable_spec.rb +109 -0
- data/spec/lib/LittleWeasel/preprocessors/word_preprocessors_validatable_spec.rb +49 -0
- data/spec/lib/LittleWeasel/services/dictionary_cache_service_spec.rb +444 -0
- data/spec/lib/LittleWeasel/services/dictionary_creator_service_spec.rb +119 -0
- data/spec/lib/LittleWeasel/services/dictionary_file_loader_service_spec.rb +71 -0
- data/spec/lib/LittleWeasel/services/dictionary_loader_service_spec.rb +50 -0
- data/spec/lib/LittleWeasel/services/dictionary_metadata_service_spec.rb +279 -0
- data/spec/lib/LittleWeasel/word_results_spec.rb +275 -0
- data/spec/lib/LittleWeasel/workflow/workflow_spec.rb +20 -0
- data/spec/spec_helper.rb +117 -6
- data/spec/support/factory_bot.rb +15 -0
- data/spec/support/file_helpers.rb +32 -0
- data/spec/support/files/empty-dictionary.txt +0 -0
- data/{lib/dictionary → spec/support/files/en-US-big.txt} +262156 -31488
- data/spec/support/files/en-US-tagged.txt +26 -0
- data/spec/support/files/en-US.txt +26 -0
- data/spec/support/files/en.txt +26 -0
- data/spec/support/files/es-ES.txt +27 -0
- data/spec/support/files/es.txt +27 -0
- data/spec/support/general_helpers.rb +68 -0
- data/spec/support/shared_contexts.rb +108 -0
- data/spec/support/shared_examples.rb +105 -0
- metadata +408 -65
- data/spec/checker/checker_spec.rb +0 -286
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'language'
|
|
4
|
+
require_relative 'region'
|
|
5
|
+
|
|
6
|
+
module LittleWeasel
|
|
7
|
+
module Modules
|
|
8
|
+
# This module provides methods to handle conversion of parts of a locale to
|
|
9
|
+
# their string counter parts.
|
|
10
|
+
module Locale
|
|
11
|
+
def self.included(base)
|
|
12
|
+
base.extend(ClassMethods)
|
|
13
|
+
base.include(Language)
|
|
14
|
+
base.include(Region)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# class method inclusions for convenience.
|
|
18
|
+
module ClassMethods
|
|
19
|
+
def locale(language:, region: nil)
|
|
20
|
+
raise ArgumentError, 'Argument language does not respond to :downcase' unless language.respond_to? :downcase
|
|
21
|
+
|
|
22
|
+
if region.present? && !region.respond_to?(:upcase)
|
|
23
|
+
raise ArgumentError,
|
|
24
|
+
'Argument region does not respond to :upcase'
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
language = normalize_language language
|
|
28
|
+
return language.to_s unless region.present?
|
|
29
|
+
|
|
30
|
+
region = normalize_region region
|
|
31
|
+
"#{language}-#{region}"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def locale
|
|
36
|
+
self.class.locale language: language, region: region
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LittleWeasel
|
|
4
|
+
module Modules
|
|
5
|
+
# This module provides methods to validate a value that can be used
|
|
6
|
+
# in sorting.
|
|
7
|
+
module OrderValidatable
|
|
8
|
+
def self.validate(order:)
|
|
9
|
+
raise ArgumentError, "Argument order is not an Integer: #{order.class}" unless order.is_a? Integer
|
|
10
|
+
raise ArgumentError, "Argument order '#{order}' is not a a number from 0-n" if order.negative?
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def validate_order(order:)
|
|
14
|
+
OrderValidatable.validate order: order
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LittleWeasel
|
|
4
|
+
module Modules
|
|
5
|
+
# This module provides attribtues and methods to manage objects that can be
|
|
6
|
+
# ordered or sorted.
|
|
7
|
+
module Orderable
|
|
8
|
+
include OrderValidatable
|
|
9
|
+
|
|
10
|
+
attr_reader :order
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
attr_writer :order
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LittleWeasel
|
|
4
|
+
module Modules
|
|
5
|
+
# Provides methods for normalizing a region for a locale.
|
|
6
|
+
module Region
|
|
7
|
+
def self.included(base)
|
|
8
|
+
base.extend(ClassMethods)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# class method inclusions for convenience.
|
|
12
|
+
module ClassMethods
|
|
13
|
+
def normalize_region(region)
|
|
14
|
+
region&.upcase
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def normalize_region
|
|
19
|
+
self.class.normalize_region region
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LittleWeasel
|
|
4
|
+
module Modules
|
|
5
|
+
# This module provides methods to validate a region.
|
|
6
|
+
module RegionValidatable
|
|
7
|
+
def self.validate(region:)
|
|
8
|
+
raise ArgumentError, "Argument region '#{region}' is not a Symbol." unless region.blank? || region.is_a?(Symbol)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def validate_region(region:)
|
|
12
|
+
RegionValidatable.validate region: region
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LittleWeasel
|
|
4
|
+
module Modules
|
|
5
|
+
# This module provides methods to validate a tag.
|
|
6
|
+
module TagValidatable
|
|
7
|
+
def self.validate(tag:)
|
|
8
|
+
raise ArgumentError, "Argument tag '#{tag}' is not a Symbol." unless tag.blank? || tag.is_a?(Symbol)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def validate_tag(tag:)
|
|
12
|
+
TagValidatable.validate tag: tag
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'tag_validatable'
|
|
4
|
+
|
|
5
|
+
module LittleWeasel
|
|
6
|
+
module Modules
|
|
7
|
+
# This module provides methods to manage objects that can be tagged.
|
|
8
|
+
# A tag is a value that can be included as part of a DictionaryKey
|
|
9
|
+
# object to make it unique across locales.
|
|
10
|
+
#
|
|
11
|
+
# @examples
|
|
12
|
+
#
|
|
13
|
+
# en-US-<tag>
|
|
14
|
+
#
|
|
15
|
+
# Where <tag> = a String to make this locale unique across locales
|
|
16
|
+
# of the same language and region.
|
|
17
|
+
module Taggable
|
|
18
|
+
include TagValidatable
|
|
19
|
+
|
|
20
|
+
attr_reader :tag
|
|
21
|
+
|
|
22
|
+
def tagged?
|
|
23
|
+
tag.present?
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
attr_writer :tag
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LittleWeasel
|
|
4
|
+
module Modules
|
|
5
|
+
# This module provides methods to validate a word results
|
|
6
|
+
module WordResultsValidatable
|
|
7
|
+
def validate_original_word
|
|
8
|
+
raise ArgumentError, "Argument original_word is not a String: #{original_word.class}" \
|
|
9
|
+
unless original_word.is_a? String
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def validate_filters_matched
|
|
13
|
+
raise ArgumentError, "Argument filters_matched is not an Array: #{filters_matched.class}" \
|
|
14
|
+
unless filters_matched.is_a? Array
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def validate_word_cached
|
|
18
|
+
raise ArgumentError, "Argument word_cached is not true or false: #{word_cached.class}" \
|
|
19
|
+
unless [true, false].include? word_cached
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def vaidate_word_valid
|
|
23
|
+
raise ArgumentError, "Argument word_valid is not true or false: #{word_cached.class}" \
|
|
24
|
+
unless [true, false].include? word_valid
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../word_preprocessor'
|
|
4
|
+
|
|
5
|
+
module LittleWeasel
|
|
6
|
+
module Preprocessors
|
|
7
|
+
module EnUs
|
|
8
|
+
# This preprocessor capitializes a word.
|
|
9
|
+
class CapitalizePreprocessor < WordPreprocessor
|
|
10
|
+
def initialize(order: 0)
|
|
11
|
+
super
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class << self
|
|
15
|
+
def preprocess(word)
|
|
16
|
+
[true, word.capitalize]
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LittleWeasel
|
|
4
|
+
module Preprocessors
|
|
5
|
+
# This class represents a word that has passed through
|
|
6
|
+
# Preprocessor::WordPreprocessor processing. Word preprocessors
|
|
7
|
+
# are used to preprocess a word before it is passed to any
|
|
8
|
+
# Filters::WordFilters, and before it is compared against the
|
|
9
|
+
# dictionary for validity.
|
|
10
|
+
class PreprocessedWord
|
|
11
|
+
attr_accessor :original_word, :preprocessed, :preprocessed_word, :preprocessor, :preprocessor_order
|
|
12
|
+
|
|
13
|
+
def initialize(original_word:, preprocessed:, preprocessed_word:, preprocessor:, preprocessor_order:)
|
|
14
|
+
self.original_word = original_word
|
|
15
|
+
self.preprocessed_word = preprocessed_word
|
|
16
|
+
self.preprocessed = preprocessed
|
|
17
|
+
self.preprocessor = preprocessor
|
|
18
|
+
self.preprocessor_order = preprocessor_order
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Returns true if the word was preprocessed; false, if the word
|
|
22
|
+
# was not preprocessed by this preprocessor.
|
|
23
|
+
def preprocessed?
|
|
24
|
+
preprocessed
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LittleWeasel
|
|
4
|
+
module Preprocessors
|
|
5
|
+
# This module provides functionality that validates preprocessed word types.
|
|
6
|
+
# rubocop: disable Layout/LineLength
|
|
7
|
+
module PreprocessedWordValidatable
|
|
8
|
+
module_function
|
|
9
|
+
|
|
10
|
+
def validate_prepreprocessed_word(preprocessed_word:)
|
|
11
|
+
validate_original_word preprocessed_word: preprocessed_word
|
|
12
|
+
validate_preprocessed_word preprocessed_word: preprocessed_word
|
|
13
|
+
validate_preprocessed preprocessed_word: preprocessed_word
|
|
14
|
+
validate_preprocessor preprocessed_word: preprocessed_word
|
|
15
|
+
validate_preprocessor_order preprocessed_word: preprocessed_word
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def validation_error_message(object:, respond_to:)
|
|
19
|
+
"Argument preprocessed_word: does not respond to: #{object}#{respond_to}"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def validate_original_word(preprocessed_word:)
|
|
23
|
+
preprocessed_word_class = preprocessed_word.class
|
|
24
|
+
raise validation_error_message(object: preprocessed_word_class, respond_to: '#original_word') unless preprocessed_word.respond_to?(:original_word)
|
|
25
|
+
raise validation_error_message(object: preprocessed_word_class, respond_to: '#original_word=') unless preprocessed_word.respond_to?(:original_word=)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def validate_preprocessed_word(preprocessed_word:)
|
|
29
|
+
preprocessed_word_class = preprocessed_word.class
|
|
30
|
+
raise validation_error_message(object: preprocessed_word_class, respond_to: '#preprocessed_word') unless preprocessed_word.respond_to?(:preprocessed_word)
|
|
31
|
+
raise validation_error_message(object: preprocessed_word_class, respond_to: '#preprocessed_word=') unless preprocessed_word.respond_to?(:preprocessed_word=)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def validate_preprocessed(preprocessed_word:)
|
|
35
|
+
preprocessed_word_class = preprocessed_word.class
|
|
36
|
+
raise validation_error_message(object: preprocessed_word_class, respond_to: '#preprocessed') unless preprocessed_word.respond_to?(:preprocessed)
|
|
37
|
+
raise validation_error_message(object: preprocessed_word_class, respond_to: '#preprocessed=') unless preprocessed_word.respond_to?(:preprocessed=)
|
|
38
|
+
raise validation_error_message(object: preprocessed_word_class, respond_to: '#preprocessed?') unless preprocessed_word.respond_to?(:preprocessed?)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def validate_preprocessor(preprocessed_word:)
|
|
42
|
+
preprocessed_word_class = preprocessed_word.class
|
|
43
|
+
raise validation_error_message(object: preprocessed_word_class, respond_to: '#preprocessor') unless preprocessed_word.respond_to?(:preprocessor)
|
|
44
|
+
raise validation_error_message(object: preprocessed_word_class, respond_to: '#preprocessor=') unless preprocessed_word.respond_to?(:preprocessor=)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def validate_preprocessor_order(preprocessed_word:)
|
|
48
|
+
preprocessed_word_class = preprocessed_word.class
|
|
49
|
+
raise validation_error_message(object: preprocessed_word_class, respond_to: '#preprocessor_order') unless preprocessed_word.respond_to?(:preprocessor_order)
|
|
50
|
+
raise validation_error_message(object: preprocessed_word_class, respond_to: '#preprocessor_order=') unless preprocessed_word.respond_to?(:preprocessor_order=)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
# rubocop: enable Layout/LineLength
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LittleWeasel
|
|
4
|
+
module Preprocessors
|
|
5
|
+
# This class provides a container for Preprocessors::PreprocessedWord
|
|
6
|
+
# objects.
|
|
7
|
+
class PreprocessedWords
|
|
8
|
+
attr_reader :original_word
|
|
9
|
+
attr_accessor :preprocessed_words
|
|
10
|
+
|
|
11
|
+
# original_word:String the unsullied word before any preprocessing has
|
|
12
|
+
# been applied to it.
|
|
13
|
+
# preprocessed_words:Array, Preprocessors::PreprocessedWord, an Array
|
|
14
|
+
# of Preprocessors::PreprocessedWord objects that represents the
|
|
15
|
+
# original_word having passed through each successive
|
|
16
|
+
# Preprocessors::WordPreprocessor.
|
|
17
|
+
def initialize(original_word:, preprocessed_words:)
|
|
18
|
+
self.original_word = original_word
|
|
19
|
+
self.preprocessed_words = preprocessed_words
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class << self
|
|
23
|
+
# Returns true if the word was passed through any preprocessing. If
|
|
24
|
+
# this is the case, #preprocessed_word may be different than
|
|
25
|
+
# #original_word.
|
|
26
|
+
def preprocessed?(preprocessed_words:)
|
|
27
|
+
# TODO: Do we need to check for preprocessors where
|
|
28
|
+
# #preprocessed? is true? or does preprocessed_words
|
|
29
|
+
# contain only preprocessed word objects where
|
|
30
|
+
# #preprocessed? is true?
|
|
31
|
+
preprocessed_words.present?
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def preprocessed_word(preprocessed_words:)
|
|
35
|
+
return unless preprocessed? preprocessed_words: preprocessed_words
|
|
36
|
+
|
|
37
|
+
preprocessed_words.max_by(&:preprocessor_order).preprocessed_word
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def preprocessed_word
|
|
42
|
+
self.class.preprocessed_word preprocessed_words: preprocessed_words
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Returns true if the word was preprocessed
|
|
46
|
+
def preprocessed?
|
|
47
|
+
self.class.preprocessed? preprocessed_words: preprocessed_words
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
attr_writer :original_word
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'preprocessed_word_validatable'
|
|
4
|
+
|
|
5
|
+
module LittleWeasel
|
|
6
|
+
module Preprocessors
|
|
7
|
+
# This module provides methods to validate preprocessed words types.
|
|
8
|
+
# rubocop: disable Layout/LineLength
|
|
9
|
+
module PreprocessedWordsValidatable
|
|
10
|
+
module_function
|
|
11
|
+
|
|
12
|
+
def validate_prepreprocessed_words(preprocessed_words:)
|
|
13
|
+
raise ArgumentError, validation_error_message(object: preprocessed_words, respond_to: :original_word) unless preprocessed_words.respond_to? :original_word
|
|
14
|
+
raise ArgumentError, validation_error_message(object: preprocessed_words, respond_to: :preprocessed_words) unless preprocessed_words.respond_to? :preprocessed_words
|
|
15
|
+
|
|
16
|
+
preprocessed_words&.preprocessed_words&.each do |preprocessed_word|
|
|
17
|
+
PreprocessedWordValidatable.validate_prepreprocessed_word preprocessed_word: preprocessed_word
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def validation_error_message(object:, respond_to:)
|
|
22
|
+
"Argument preprocessed_words does not respond to: #{object.class}##{respond_to}"
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
# rubocop: enable Layout/LineLength
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'word_preprocessors_validatable'
|
|
4
|
+
|
|
5
|
+
module LittleWeasel
|
|
6
|
+
module Preprocessors
|
|
7
|
+
# This module provides the word_preprocessors attribute for objects
|
|
8
|
+
# that support word preprocessors.
|
|
9
|
+
module WordPreprocessable
|
|
10
|
+
@word_preprocessors = []
|
|
11
|
+
|
|
12
|
+
attr_reader :word_preprocessors
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
attr_writer :word_preprocessors
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../errors/must_override_error'
|
|
4
|
+
require_relative '../modules/class_name_to_symbol'
|
|
5
|
+
require_relative '../modules/orderable'
|
|
6
|
+
require_relative 'preprocessed_word'
|
|
7
|
+
|
|
8
|
+
module LittleWeasel
|
|
9
|
+
module Preprocessors
|
|
10
|
+
# This is a base class that provides methods and functionality for
|
|
11
|
+
# word preprocessors. A "word preprocessor" is an object that manipulates a
|
|
12
|
+
# word before it is passed to any word filters and before it is compared
|
|
13
|
+
# against the dictionary for validity.
|
|
14
|
+
class WordPreprocessor
|
|
15
|
+
include Modules::ClassNameToSymbol
|
|
16
|
+
include Modules::Orderable
|
|
17
|
+
|
|
18
|
+
attr_reader :preprocessor_on
|
|
19
|
+
|
|
20
|
+
# order:Integer, the order in which this preprocessor should
|
|
21
|
+
# be applied.
|
|
22
|
+
# preprocessor_on:Boolean, whether or not this preprocessor
|
|
23
|
+
# should be applied to any words.
|
|
24
|
+
def initialize(order:)
|
|
25
|
+
validate_order order: order
|
|
26
|
+
self.order = order
|
|
27
|
+
preprocessor_on!
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class << self
|
|
31
|
+
# Should return true if word matches the preprocess criteria;
|
|
32
|
+
# false, otherwise. If this preprocessor has no preprocess criteria,
|
|
33
|
+
# simply return true. This class method is unlike the instance method in
|
|
34
|
+
# that it does not consider whether or not this preprocessor is "on"
|
|
35
|
+
# or "off"; it simply returns true or false based on whether or not the
|
|
36
|
+
# word matches the preprocess criteria.
|
|
37
|
+
def preprocess?(_word)
|
|
38
|
+
true
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# This method should UNconditionally apply preprocessing to word ONLY if
|
|
42
|
+
# word meets the criteria for preprocessing (.preprocess?).
|
|
43
|
+
#
|
|
44
|
+
# This method should return the following Array:
|
|
45
|
+
#
|
|
46
|
+
# [<preprocessed?>, <preprocessed word | nil>]
|
|
47
|
+
#
|
|
48
|
+
# Where:
|
|
49
|
+
#
|
|
50
|
+
# <preprocessed?> == whether or not the word was preprocessed
|
|
51
|
+
# based on whether or not the word meets the preprocessing
|
|
52
|
+
# criteria (.preprocess?).
|
|
53
|
+
#
|
|
54
|
+
# <preprocessed word | nil> == the preprocessed word (if word
|
|
55
|
+
# met the preprocessing criteria (.preprocessed?)) or nil if
|
|
56
|
+
# word was NOT preprocessed (word did NOT meet the preprocessing
|
|
57
|
+
# criteria).
|
|
58
|
+
def preprocess(_word)
|
|
59
|
+
raise Errors::MustOverrideError
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def preprocessor_on=(value)
|
|
64
|
+
raise ArgumentError, "Argument value is not true or false: #{value}" \
|
|
65
|
+
unless [true, false].include? value
|
|
66
|
+
|
|
67
|
+
@preprocessor_on = value
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Returns true if word meets the criteria for preprocessing. false
|
|
71
|
+
# is returned if word does not meet the criteria for preprocessing, or,
|
|
72
|
+
# if the preprocessor is "off".
|
|
73
|
+
def preprocess?(word)
|
|
74
|
+
return false if preprocessor_off?
|
|
75
|
+
|
|
76
|
+
self.class.preprocess? word
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Applies preprocessing to word if this preprocessor is "on" AND if word
|
|
80
|
+
# meets the criteria for preprocessing; no preprocessing is applied to
|
|
81
|
+
# word otherwise.
|
|
82
|
+
#
|
|
83
|
+
# This method should return a Preprocessors::PreprocessedWord object.
|
|
84
|
+
def preprocess(word)
|
|
85
|
+
preprocessed, preprocessed_word = if preprocessor_on?
|
|
86
|
+
self.class.preprocess word
|
|
87
|
+
else
|
|
88
|
+
[false, nil]
|
|
89
|
+
end
|
|
90
|
+
preprocessed_word(original_word: word, preprocessed_word: preprocessed_word, preprocessed: preprocessed)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Returns true if this preprocessor is "on"; false, otherwise. If this
|
|
94
|
+
# preprocessor is "on", preprocessing should be applied to a word if word
|
|
95
|
+
# meets the criteria for preprocessing.
|
|
96
|
+
def preprocessor_on?
|
|
97
|
+
preprocessor_on
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def preprocessor_on!
|
|
101
|
+
@preprocessor_on = true
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Returns true if this preprocessor is "off". Preprocessing should not
|
|
105
|
+
# be applied to a word if this preprocessor is "off".
|
|
106
|
+
def preprocessor_off?
|
|
107
|
+
!preprocessor_on?
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def preprocessor_off!
|
|
111
|
+
@preprocessor_on = false
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
private
|
|
115
|
+
|
|
116
|
+
def preprocessed_word(original_word:, preprocessed:, preprocessed_word:)
|
|
117
|
+
PreprocessedWord.new(original_word: original_word, preprocessed: preprocessed,
|
|
118
|
+
preprocessed_word: preprocessed_word, preprocessor: to_sym, preprocessor_order: order)
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|