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.
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
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LittleWeasel
4
+ module Modules
5
+ # This module provides convienience methods for accessing this gem's
6
+ # configuration.
7
+ module Configurable
8
+ def self.included(base)
9
+ base.extend(ClassMethods)
10
+ end
11
+
12
+ # class method inclusions for convenience.
13
+ module ClassMethods
14
+ def config
15
+ LittleWeasel.configuration
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def config
22
+ @config ||= self.class.config
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LittleWeasel
4
+ module Modules
5
+ # This module simply includes ActiveSupport's core for #deep_dup support. If
6
+ # we ever want to roll our own, we can do so here.
7
+ module DeepDup
8
+ require 'active_support/core_ext/object/deep_dup'
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LittleWeasel
4
+ module Modules
5
+ # This module provides methods and constants used to define, initialize
6
+ # and manipulate a dictionary cache Hash object.
7
+ module DictionaryCacheKeys
8
+ DICTIONARY_CACHE = 'dictionary_cache'
9
+ DICTIONARY_REFERENCES = 'dictionary_references'
10
+ DICTIONARY_ID = 'dictionary_id'
11
+ DICTIONARIES = 'dictionaries'
12
+ SOURCE = 'source'
13
+ DICTIONARY_OBJECT = 'dictionary_object'
14
+
15
+ module_function
16
+
17
+ def initialize_dictionary_cache(dictionary_cache:)
18
+ dictionary_cache.each_key { |key| dictionary_cache.delete(key) }
19
+ dictionary_cache[DICTIONARY_CACHE] = initialized_dictionary_cache(include_root: false)
20
+ dictionary_cache
21
+ end
22
+
23
+ def initialized_dictionary_cache(include_root: true)
24
+ dictionary_cache = {
25
+ DICTIONARY_REFERENCES => {},
26
+ DICTIONARIES => {}
27
+ }
28
+ return { DICTIONARY_CACHE => dictionary_cache } if include_root
29
+
30
+ dictionary_cache
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../dictionary_key'
4
+ require_relative '../services/dictionary_cache_service'
5
+ require_relative 'dictionary_cache_validatable'
6
+
7
+ module LittleWeasel
8
+ module Modules
9
+ # This module defines methods and attributes to consume the dictionary
10
+ # cache service.
11
+ module DictionaryCacheServicable
12
+ include DictionaryKeyable
13
+ include DictionaryCacheValidatable
14
+
15
+ attr_reader :dictionary_cache, :dictionary_key
16
+
17
+ def dictionary_cache_service
18
+ Services::DictionaryCacheService.new(dictionary_key: dictionary_key, dictionary_cache: dictionary_cache)
19
+ end
20
+
21
+ private
22
+
23
+ attr_writer :dictionary_cache, :dictionary_key
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LittleWeasel
4
+ module Modules
5
+ # This module provides methods to validate a dictionary cache object.
6
+ # A dictionary cache object is a container that holds cached data
7
+ # related to one or more dictionaries. Dictionary cache objects are
8
+ # normally specific to a DictionaryManager object.
9
+ module DictionaryCacheValidatable
10
+ def self.validate(dictionary_cache:)
11
+ raise ArgumentError, "Argument dictionary_cache is not a valid Hash object: #{dictionary_cache.class}" \
12
+ unless dictionary_cache.is_a? Hash
13
+ end
14
+
15
+ def validate_dictionary_cache(dictionary_cache:)
16
+ DictionaryCacheValidatable.validate dictionary_cache: dictionary_cache
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../dictionary_key'
4
+ require_relative '../services/dictionary_cache_service'
5
+ require_relative '../filters/word_filters_validatable'
6
+
7
+ module LittleWeasel
8
+ module Modules
9
+ # This module defines methods and attributes to consume the dictionary
10
+ # creator service.
11
+ module DictionaryCreatorServicable
12
+ include DictionaryKeyable
13
+ include Filters::WordFiltersValidatable
14
+
15
+ attr_reader :dictionary_cache, :dictionary_key, :word_filters
16
+
17
+ def dictionary_creator_service
18
+ Services::DictionaryCreatorService.new(dictionary_key: dictionary_key, dictionary_cache: dictionary_cache,
19
+ dictionary_metadata: dictionary_metadata, word_filters: word_filters)
20
+ end
21
+
22
+ private
23
+
24
+ attr_writer :dictionary_cache, :dictionary_key, :word_filters
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../errors/dictionary_file_already_loaded_error'
4
+ require_relative '../errors/dictionary_file_empty_error'
5
+ require_relative '../errors/dictionary_file_not_found_error'
6
+ require_relative '../errors/dictionary_file_too_large_error'
7
+
8
+ module LittleWeasel
9
+ module Modules
10
+ # Defines methods to load dictionaries. The dictionary file path is used
11
+ # as a key to avoid loading the same dictionary multiple times.
12
+ module DictionaryFileLoader
13
+ def load(dictionary_file_path)
14
+ Loader.new(dictionary_file_path, config).load
15
+ end
16
+
17
+ # Helps with dictionary loading.
18
+ class Loader
19
+ def initialize(dictionary_file_path, config)
20
+ self.dictionary_file_path = dictionary_file_path
21
+ self.config = config
22
+ end
23
+
24
+ # Loads but DOES NOT update the dictionaries_hash. Use this if the dictionary
25
+ # DOES NOT need to hang around for any length of time.
26
+ def load
27
+ raise Errors::DictionaryFileNotFoundError unless file_exist?
28
+ raise Errors::DictionaryFileEmptyError if file_empty?
29
+ raise Errors::DictionaryFileTooLargeError if file_too_large?
30
+
31
+ load_dictionary
32
+ end
33
+
34
+ private
35
+
36
+ attr_accessor :config, :dictionary_file_path, :dictionary_words
37
+
38
+ def load_dictionary
39
+ prepare_dictionary(File.read(dictionary_file_path, mode: 'r')&.split)
40
+ end
41
+
42
+ def prepare_dictionary(words)
43
+ words&.uniq!&.compact!
44
+ words if words.present?
45
+ end
46
+
47
+ def file_size
48
+ # File.size? returns nil if file_name doesn't exist or has zero size,
49
+ # the size of the file otherwise.
50
+ @file_size ||= File.size?(dictionary_file_path) || 0
51
+ end
52
+
53
+ def file_exist?
54
+ @file_exist ||= File.exist? dictionary_file_path
55
+ end
56
+
57
+ def file_empty?
58
+ @file_empty ||= file_exist? && file_size.zero?
59
+ end
60
+
61
+ def file_too_large?
62
+ @file_too_large ||= file_exist? && file_size > config.max_dictionary_file_bytes
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../dictionary_key'
4
+
5
+ module LittleWeasel
6
+ module Modules
7
+ # Provides methods to validate a dictionary key object.
8
+ module DictionaryKeyValidatable
9
+ def self.validate(dictionary_key:)
10
+ raise ArgumentError, "Argument dictionary_key is not a valid DictionaryKey object: #{dictionary_key.class}" \
11
+ unless dictionary_key.is_a? DictionaryKey
12
+ end
13
+
14
+ def validate_dictionary_key(dictionary_key:)
15
+ DictionaryKeyValidatable.validate(dictionary_key: dictionary_key)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/core_ext/module/delegation'
4
+ require_relative 'dictionary_key_validatable'
5
+
6
+ module LittleWeasel
7
+ module Modules
8
+ # This module defines attributes and functionality for a dictionary
9
+ # key. A dictionary key is a unique key (basically a locale and optional
10
+ # tag suffix) that is used to link a dictionary to the dictionary cache
11
+ # and dictionary metadata objects.
12
+ module DictionaryKeyable
13
+ include Modules::DictionaryKeyValidatable
14
+
15
+ attr_reader :dictionary_key
16
+
17
+ delegate :key, to: :dictionary_key
18
+
19
+ private
20
+
21
+ attr_writer :dictionary_key
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../dictionary_key'
4
+ require_relative '../services/dictionary_loader_service'
5
+ require_relative 'dictionary_cache_validatable'
6
+
7
+ module LittleWeasel
8
+ module Modules
9
+ # This module defines methods and attributes to consume the dictionary
10
+ # loader service.
11
+ module DictionaryLoaderServicable
12
+ include DictionaryCacheValidatable
13
+ include DictionaryKeyable
14
+
15
+ attr_reader :dictionary_cache, :dictionary_key, :dictionary_metadata
16
+
17
+ def dictionary_loader_service
18
+ Services::DictionaryLoaderService.new(dictionary_key: dictionary_key, dictionary_cache: dictionary_cache,
19
+ dictionary_metadata: dictionary_metadata)
20
+ end
21
+
22
+ private
23
+
24
+ attr_writer :dictionary_cache, :dictionary_key, :dictionary_metadata
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../dictionary_key'
4
+ require_relative '../services/dictionary_metadata_service'
5
+ require_relative 'dictionary_cache_validatable'
6
+ require_relative 'dictionary_metadata_validatable'
7
+
8
+ module LittleWeasel
9
+ module Modules
10
+ # This module defines methods and attributes to consume the dictionary
11
+ # metadata service.
12
+ module DictionaryMetadataServicable
13
+ include DictionaryKeyable
14
+ include DictionaryCacheValidatable
15
+ include DictionaryMetadataValidatable
16
+
17
+ attr_reader :dictionary_cache, :dictionary_key, :dictionary_metadata
18
+
19
+ def dictionary_metadata_service
20
+ Services::DictionaryMetadataService.new(dictionary_key: dictionary_key, dictionary_cache: dictionary_cache,
21
+ dictionary_metadata: dictionary_metadata)
22
+ end
23
+
24
+ private
25
+
26
+ attr_writer :dictionary_cache, :dictionary_key, :dictionary_metadata
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LittleWeasel
4
+ module Modules
5
+ # This module provides methods to validate a dictionary metadata object.
6
+ module DictionaryMetadataValidatable
7
+ def self.validate(dictionary_metadata:)
8
+ raise ArgumentError, "Argument dictionary_metadata is not a valid Hash object: #{dictionary_metadata.class}" \
9
+ unless dictionary_metadata.is_a? Hash
10
+ end
11
+
12
+ def validate_dictionary_metadata(dictionary_metadata:)
13
+ DictionaryMetadataValidatable.validate dictionary_metadata: dictionary_metadata
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module LittleWeasel
6
+ module Modules
7
+ # This module provides methods to manage dictionary sources.
8
+ module DictionarySourceable
9
+ MEMORY_SOURCE = '*'
10
+
11
+ module_function
12
+
13
+ def file_source?(source)
14
+ !memory_source? source
15
+ end
16
+
17
+ def memory_source?(source)
18
+ source =~ /^#{Regexp.quote(MEMORY_SOURCE)}[0-9a-fA-F]{8}$/
19
+ end
20
+
21
+ def memory_source
22
+ "#{MEMORY_SOURCE}#{SecureRandom.uuid[0..7]}"
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LittleWeasel
4
+ module Modules
5
+ # This module provides validations related to dictionaries in
6
+ # the dictionary cache.
7
+ module DictionaryValidatable
8
+ module_function
9
+
10
+ def validate_dictionary_source_does_not_exist(dictionary_cache_service:)
11
+ # If a dictionary_reference exists, the dictionary_source must exist.
12
+ if dictionary_cache_service.dictionary_reference?
13
+ raise "The dictionary source associated with key '#{dictionary_cache_service.key}' already exists."
14
+ end
15
+ end
16
+
17
+ def validate_dictionary_does_not_exist(dictionary_cache_service:)
18
+ if dictionary_cache_service.dictionary_exists?
19
+ raise "The dictionary associated with key '#{dictionary_cache_service.key}' already exists."
20
+ end
21
+ end
22
+
23
+ def validate_dictionary_reference_does_not_exist(dictionary_cache_service:)
24
+ if dictionary_cache_service.dictionary_reference?
25
+ raise "A dictionary reference associated with key '#{dictionary_cache_service.key}' already exists."
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LittleWeasel
4
+ module Modules
5
+ # Provides methods for normalizing language for a locale.
6
+ module Language
7
+ def self.included(base)
8
+ base.extend(ClassMethods)
9
+ end
10
+
11
+ # class method inclusions for convenience.
12
+ module ClassMethods
13
+ def normalize_language(language)
14
+ language&.downcase
15
+ end
16
+ end
17
+
18
+ def normalize_language
19
+ self.class.normalize_language language
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 language.
6
+ module LanguageValidatable
7
+ def self.validate(language:)
8
+ raise ArgumentError, "Argument language '#{language}' is not a Symbol." unless language.is_a? Symbol
9
+ end
10
+
11
+ def validate_language(language:)
12
+ LanguageValidatable.validate language: language
13
+ end
14
+ end
15
+ end
16
+ end