picky 1.4.1 → 1.4.2

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 (229) hide show
  1. data/lib/picky/{alias_instances.rb → aliases.rb} +1 -3
  2. data/lib/picky/application.rb +18 -19
  3. data/lib/picky/cores.rb +1 -1
  4. data/lib/picky/generators/aliases.rb +3 -0
  5. data/lib/picky/index/base.rb +179 -0
  6. data/lib/picky/index/memory.rb +28 -0
  7. data/lib/picky/index/redis.rb +28 -0
  8. data/lib/picky/{indexes_api.rb → index_bundle.rb} +16 -16
  9. data/lib/picky/indexed/indexes.rb +11 -7
  10. data/lib/picky/indexing/indexes.rb +14 -8
  11. data/lib/picky/internals/adapters/rack/base.rb +27 -0
  12. data/lib/picky/internals/adapters/rack/live_parameters.rb +37 -0
  13. data/lib/picky/internals/adapters/rack/query.rb +63 -0
  14. data/lib/picky/internals/adapters/rack.rb +34 -0
  15. data/lib/picky/{calculations → internals/calculations}/location.rb +0 -0
  16. data/lib/picky/{cli.rb → internals/cli.rb} +0 -0
  17. data/lib/picky/{configuration → internals/configuration}/index.rb +8 -2
  18. data/lib/picky/{ext → internals/ext}/maybe_compile.rb +0 -0
  19. data/lib/picky/{ext → internals/ext}/ruby19/extconf.rb +0 -0
  20. data/lib/picky/{ext → internals/ext}/ruby19/performant.c +0 -0
  21. data/lib/picky/{extensions → internals/extensions}/array.rb +0 -0
  22. data/lib/picky/{extensions → internals/extensions}/hash.rb +0 -0
  23. data/lib/picky/{extensions → internals/extensions}/module.rb +0 -0
  24. data/lib/picky/{extensions → internals/extensions}/object.rb +0 -0
  25. data/lib/picky/{extensions → internals/extensions}/symbol.rb +0 -0
  26. data/lib/picky/internals/frontend_adapters/rack.rb +154 -0
  27. data/lib/picky/internals/generators/base.rb +19 -0
  28. data/lib/picky/internals/generators/partial/default.rb +7 -0
  29. data/lib/picky/internals/generators/partial/none.rb +35 -0
  30. data/lib/picky/internals/generators/partial/strategy.rb +29 -0
  31. data/lib/picky/internals/generators/partial/substring.rb +122 -0
  32. data/lib/picky/internals/generators/partial_generator.rb +19 -0
  33. data/lib/picky/internals/generators/similarity/default.rb +9 -0
  34. data/lib/picky/internals/generators/similarity/double_levenshtone.rb +81 -0
  35. data/lib/picky/internals/generators/similarity/none.rb +35 -0
  36. data/lib/picky/internals/generators/similarity/strategy.rb +11 -0
  37. data/lib/picky/internals/generators/similarity_generator.rb +19 -0
  38. data/lib/picky/internals/generators/strategy.rb +18 -0
  39. data/lib/picky/internals/generators/weights/default.rb +9 -0
  40. data/lib/picky/internals/generators/weights/logarithmic.rb +43 -0
  41. data/lib/picky/internals/generators/weights/strategy.rb +11 -0
  42. data/lib/picky/internals/generators/weights_generator.rb +19 -0
  43. data/lib/picky/{helpers → internals/helpers}/measuring.rb +0 -0
  44. data/lib/picky/internals/index/backend.rb +113 -0
  45. data/lib/picky/internals/index/file/basic.rb +101 -0
  46. data/lib/picky/internals/index/file/json.rb +38 -0
  47. data/lib/picky/internals/index/file/marshal.rb +38 -0
  48. data/lib/picky/internals/index/file/text.rb +60 -0
  49. data/lib/picky/internals/index/files.rb +24 -0
  50. data/lib/picky/internals/index/redis/basic.rb +77 -0
  51. data/lib/picky/internals/index/redis/list_hash.rb +46 -0
  52. data/lib/picky/internals/index/redis/string_hash.rb +35 -0
  53. data/lib/picky/internals/index/redis.rb +44 -0
  54. data/lib/picky/internals/indexed/bundle/base.rb +72 -0
  55. data/lib/picky/internals/indexed/bundle/memory.rb +69 -0
  56. data/lib/picky/internals/indexed/bundle/redis.rb +70 -0
  57. data/lib/picky/internals/indexed/categories.rb +135 -0
  58. data/lib/picky/internals/indexed/category.rb +90 -0
  59. data/lib/picky/internals/indexed/index.rb +57 -0
  60. data/lib/picky/{indexed → internals/indexed}/wrappers/bundle/calculation.rb +0 -0
  61. data/lib/picky/{indexed → internals/indexed}/wrappers/bundle/location.rb +4 -2
  62. data/lib/picky/{indexed → internals/indexed}/wrappers/bundle/wrapper.rb +1 -1
  63. data/lib/picky/internals/indexed/wrappers/exact_first.rb +65 -0
  64. data/lib/picky/{indexers → internals/indexers}/no_source_specified_error.rb +0 -0
  65. data/lib/picky/{indexers → internals/indexers}/serial.rb +2 -2
  66. data/lib/picky/{indexers → internals/indexers}/solr.rb +0 -0
  67. data/lib/picky/internals/indexing/bundle/base.rb +219 -0
  68. data/lib/picky/internals/indexing/bundle/memory.rb +25 -0
  69. data/lib/picky/internals/indexing/bundle/redis.rb +28 -0
  70. data/lib/picky/internals/indexing/bundle/super_base.rb +65 -0
  71. data/lib/picky/internals/indexing/categories.rb +42 -0
  72. data/lib/picky/internals/indexing/category.rb +120 -0
  73. data/lib/picky/internals/indexing/index.rb +67 -0
  74. data/lib/picky/{performant.rb → internals/performant.rb} +0 -0
  75. data/lib/picky/internals/query/allocation.rb +88 -0
  76. data/lib/picky/internals/query/allocations.rb +137 -0
  77. data/lib/picky/internals/query/combination.rb +80 -0
  78. data/lib/picky/internals/query/combinations/base.rb +84 -0
  79. data/lib/picky/internals/query/combinations/memory.rb +58 -0
  80. data/lib/picky/internals/query/combinations/redis.rb +59 -0
  81. data/lib/picky/internals/query/indexes.rb +180 -0
  82. data/lib/picky/internals/query/qualifiers.rb +81 -0
  83. data/lib/picky/internals/query/token.rb +215 -0
  84. data/lib/picky/internals/query/tokens.rb +89 -0
  85. data/lib/picky/{query → internals/query}/weights.rb +0 -0
  86. data/lib/picky/internals/results/base.rb +106 -0
  87. data/lib/picky/internals/results/full.rb +17 -0
  88. data/lib/picky/internals/results/live.rb +17 -0
  89. data/lib/picky/{solr → internals/solr}/schema_generator.rb +0 -0
  90. data/lib/picky/internals/tokenizers/base.rb +166 -0
  91. data/lib/picky/internals/tokenizers/index.rb +63 -0
  92. data/lib/picky/internals/tokenizers/query.rb +79 -0
  93. data/lib/picky/loader.rb +148 -112
  94. data/lib/picky/query/base.rb +57 -26
  95. data/lib/picky/query/full.rb +1 -1
  96. data/lib/picky/query/live.rb +1 -1
  97. data/lib/picky/sources/db.rb +27 -6
  98. data/lib/tasks/index.rake +3 -3
  99. data/lib/tasks/try.rake +2 -2
  100. data/spec/lib/aliases_spec.rb +9 -0
  101. data/spec/lib/application_spec.rb +3 -3
  102. data/spec/lib/generators/aliases_spec.rb +1 -0
  103. data/spec/lib/{index_api_spec.rb → index/base_spec.rb} +7 -7
  104. data/spec/lib/index_bundle_spec.rb +71 -0
  105. data/spec/lib/indexed/indexes_spec.rb +61 -0
  106. data/spec/lib/indexing/indexes_spec.rb +94 -24
  107. data/spec/lib/{adapters → internals/adapters}/rack/base_spec.rb +2 -2
  108. data/spec/lib/{adapters → internals/adapters}/rack/live_parameters_spec.rb +2 -2
  109. data/spec/lib/{adapters → internals/adapters}/rack/query_spec.rb +2 -2
  110. data/spec/lib/{calculations → internals/calculations}/location_spec.rb +0 -0
  111. data/spec/lib/{cli_spec.rb → internals/cli_spec.rb} +4 -1
  112. data/spec/lib/{configuration → internals/configuration}/index_spec.rb +1 -1
  113. data/spec/lib/{cores_spec.rb → internals/cores_spec.rb} +0 -0
  114. data/spec/lib/{extensions → internals/extensions}/array_spec.rb +0 -0
  115. data/spec/lib/{extensions → internals/extensions}/hash_spec.rb +0 -0
  116. data/spec/lib/{extensions → internals/extensions}/module_spec.rb +0 -0
  117. data/spec/lib/{extensions → internals/extensions}/object_spec.rb +0 -0
  118. data/spec/lib/{extensions → internals/extensions}/symbol_spec.rb +0 -0
  119. data/spec/lib/{frontend_adapters → internals/frontend_adapters}/rack_spec.rb +11 -11
  120. data/spec/lib/{cacher → internals/generators}/cacher_strategy_spec.rb +2 -2
  121. data/spec/lib/internals/generators/partial/default_spec.rb +17 -0
  122. data/spec/lib/internals/generators/partial/none_spec.rb +17 -0
  123. data/spec/lib/{cacher → internals/generators}/partial/substring_spec.rb +26 -27
  124. data/spec/lib/{cacher → internals/generators}/partial_generator_spec.rb +5 -5
  125. data/spec/lib/{cacher → internals/generators}/similarity/double_levenshtone_spec.rb +4 -4
  126. data/spec/lib/{cacher → internals/generators}/similarity/none_spec.rb +2 -2
  127. data/spec/lib/{cacher → internals/generators}/similarity_generator_spec.rb +4 -4
  128. data/spec/lib/{cacher → internals/generators}/weights/logarithmic_spec.rb +2 -2
  129. data/spec/lib/internals/generators/weights_generator_spec.rb +21 -0
  130. data/spec/lib/{helpers → internals/helpers}/measuring_spec.rb +0 -0
  131. data/spec/lib/{index → internals/index}/file/basic_spec.rb +2 -2
  132. data/spec/lib/{index → internals/index}/file/json_spec.rb +2 -2
  133. data/spec/lib/{index → internals/index}/file/marshal_spec.rb +2 -2
  134. data/spec/lib/{index → internals/index}/file/text_spec.rb +2 -2
  135. data/spec/lib/{index → internals/index}/files_spec.rb +2 -2
  136. data/spec/lib/{indexed/bundle_spec.rb → internals/indexed/bundle/memory_spec.rb} +4 -5
  137. data/spec/lib/{indexed → internals/indexed}/categories_spec.rb +13 -13
  138. data/spec/lib/{indexed → internals/indexed}/category_spec.rb +59 -32
  139. data/spec/lib/{indexed → internals/indexed}/index_spec.rb +5 -5
  140. data/spec/lib/{indexed → internals/indexed}/wrappers/bundle/calculation_spec.rb +0 -0
  141. data/spec/lib/{indexed → internals/indexed}/wrappers/bundle/wrapper_spec.rb +0 -0
  142. data/spec/lib/{indexed → internals/indexed}/wrappers/exact_first_spec.rb +5 -5
  143. data/spec/lib/{indexers → internals/indexers}/serial_spec.rb +0 -0
  144. data/spec/lib/{indexing/bundle_partial_generation_speed_spec.rb → internals/indexing/bundle/memory_partial_generation_speed_spec.rb} +3 -3
  145. data/spec/lib/{indexing/bundle_spec.rb → internals/indexing/bundle/memory_spec.rb} +3 -3
  146. data/spec/lib/{index/bundle_spec.rb → internals/indexing/bundle/super_base_spec.rb} +9 -3
  147. data/spec/lib/{indexing → internals/indexing}/category_spec.rb +3 -3
  148. data/spec/lib/{indexing → internals/indexing}/index_spec.rb +3 -3
  149. data/spec/lib/internals/indexing/indexes_spec.rb +36 -0
  150. data/spec/lib/{interfaces → internals/interfaces}/live_parameters_spec.rb +0 -0
  151. data/spec/lib/internals/results/base_spec.rb +105 -0
  152. data/spec/lib/internals/results/full_spec.rb +78 -0
  153. data/spec/lib/internals/results/live_spec.rb +88 -0
  154. data/spec/lib/{solr → internals/solr}/schema_generator_spec.rb +0 -0
  155. data/spec/lib/{tokenizers → internals/tokenizers}/base_spec.rb +3 -3
  156. data/spec/lib/{tokenizers → internals/tokenizers}/index_spec.rb +9 -9
  157. data/spec/lib/{tokenizers → internals/tokenizers}/query_spec.rb +11 -11
  158. data/spec/lib/query/allocation_spec.rb +12 -12
  159. data/spec/lib/query/allocations_spec.rb +19 -19
  160. data/spec/lib/query/base_spec.rb +28 -4
  161. data/spec/lib/query/combination_spec.rb +8 -9
  162. data/spec/lib/query/combinations/base_spec.rb +116 -0
  163. data/spec/lib/query/{combinations_spec.rb → combinations/memory_spec.rb} +14 -14
  164. data/spec/lib/query/combinations/redis_spec.rb +132 -0
  165. data/spec/lib/query/full_spec.rb +2 -2
  166. data/spec/lib/query/indexes_spec.rb +81 -0
  167. data/spec/lib/query/live_spec.rb +3 -3
  168. data/spec/lib/query/qualifiers_spec.rb +6 -6
  169. data/spec/lib/query/token_spec.rb +38 -38
  170. data/spec/lib/query/tokens_spec.rb +35 -35
  171. data/spec/lib/sources/db_spec.rb +23 -18
  172. metadata +212 -181
  173. data/lib/picky/adapters/rack/base.rb +0 -23
  174. data/lib/picky/adapters/rack/live_parameters.rb +0 -33
  175. data/lib/picky/adapters/rack/query.rb +0 -59
  176. data/lib/picky/adapters/rack.rb +0 -28
  177. data/lib/picky/cacher/convenience.rb +0 -3
  178. data/lib/picky/cacher/generator.rb +0 -15
  179. data/lib/picky/cacher/partial/default.rb +0 -5
  180. data/lib/picky/cacher/partial/none.rb +0 -31
  181. data/lib/picky/cacher/partial/strategy.rb +0 -21
  182. data/lib/picky/cacher/partial/substring.rb +0 -118
  183. data/lib/picky/cacher/partial_generator.rb +0 -15
  184. data/lib/picky/cacher/similarity/default.rb +0 -7
  185. data/lib/picky/cacher/similarity/double_levenshtone.rb +0 -77
  186. data/lib/picky/cacher/similarity/none.rb +0 -31
  187. data/lib/picky/cacher/similarity/strategy.rb +0 -9
  188. data/lib/picky/cacher/similarity_generator.rb +0 -15
  189. data/lib/picky/cacher/strategy.rb +0 -12
  190. data/lib/picky/cacher/weights/default.rb +0 -7
  191. data/lib/picky/cacher/weights/logarithmic.rb +0 -39
  192. data/lib/picky/cacher/weights/strategy.rb +0 -9
  193. data/lib/picky/cacher/weights_generator.rb +0 -15
  194. data/lib/picky/frontend_adapters/rack.rb +0 -150
  195. data/lib/picky/index/bundle.rb +0 -54
  196. data/lib/picky/index/file/basic.rb +0 -97
  197. data/lib/picky/index/file/json.rb +0 -34
  198. data/lib/picky/index/file/marshal.rb +0 -34
  199. data/lib/picky/index/file/text.rb +0 -56
  200. data/lib/picky/index/files.rb +0 -118
  201. data/lib/picky/index_api.rb +0 -175
  202. data/lib/picky/indexed/bundle.rb +0 -54
  203. data/lib/picky/indexed/categories.rb +0 -131
  204. data/lib/picky/indexed/category.rb +0 -85
  205. data/lib/picky/indexed/index.rb +0 -39
  206. data/lib/picky/indexed/wrappers/exact_first.rb +0 -61
  207. data/lib/picky/indexing/bundle.rb +0 -213
  208. data/lib/picky/indexing/categories.rb +0 -38
  209. data/lib/picky/indexing/category.rb +0 -117
  210. data/lib/picky/indexing/index.rb +0 -55
  211. data/lib/picky/query/allocation.rb +0 -82
  212. data/lib/picky/query/allocations.rb +0 -130
  213. data/lib/picky/query/combination.rb +0 -74
  214. data/lib/picky/query/combinations.rb +0 -105
  215. data/lib/picky/query/qualifiers.rb +0 -77
  216. data/lib/picky/query/token.rb +0 -202
  217. data/lib/picky/query/tokens.rb +0 -86
  218. data/lib/picky/query/weigher.rb +0 -165
  219. data/lib/picky/results/base.rb +0 -102
  220. data/lib/picky/results/full.rb +0 -13
  221. data/lib/picky/results/live.rb +0 -13
  222. data/lib/picky/tokenizers/base.rb +0 -161
  223. data/lib/picky/tokenizers/index.rb +0 -58
  224. data/lib/picky/tokenizers/query.rb +0 -74
  225. data/spec/lib/cacher/partial/default_spec.rb +0 -15
  226. data/spec/lib/cacher/partial/none_spec.rb +0 -17
  227. data/spec/lib/cacher/weights_generator_spec.rb +0 -21
  228. data/spec/lib/results/base_spec.rb +0 -257
  229. data/spec/lib/results/live_spec.rb +0 -15
@@ -0,0 +1,34 @@
1
+ module Internals
2
+
3
+ module Adapters
4
+
5
+ # This is an adapter that is plugged into a Rack outlet.
6
+ #
7
+ # It looks at what is given to it and generate an appropriate
8
+ # adapter for it.
9
+ #
10
+ # For example, if you give it a query, it will extract the query param etc.
11
+ # and call search_with_text on it if it is called by Rack.
12
+ #
13
+ # Usage:
14
+ # Adapters::Rack.app_for(thing, options)
15
+ #
16
+ module Rack
17
+
18
+ # Generates the appropriate app for Rack.
19
+ #
20
+ @@mapping = {
21
+ :search_with_text => Query,
22
+ :parameters => LiveParameters
23
+ }
24
+ def self.app_for thing, options = {}
25
+ @@mapping.each_pair do |method, adapter|
26
+ return adapter.new(thing).to_app(options) if thing.respond_to?(method)
27
+ end
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+
34
+ end
File without changes
@@ -33,7 +33,7 @@ module Configuration # :nodoc:all
33
33
  @prepared_index_path ||= "#{index_directory}/prepared_#{category_name}_index"
34
34
  end
35
35
  def prepared_index_file &block
36
- @prepared_index_file ||= ::Index::File::Text.new prepared_index_path
36
+ @prepared_index_file ||= Internals::Index::File::Text.new prepared_index_path
37
37
  @prepared_index_file.open_for_indexing &block
38
38
  end
39
39
 
@@ -41,8 +41,14 @@ module Configuration # :nodoc:all
41
41
  # @file_name ||= "#{@index_name}_#{@category_name}"
42
42
  # end
43
43
 
44
+ # Identifier for internal use.
45
+ #
44
46
  def identifier
45
- @identifier ||= "#{index_name} #{category_name}"
47
+ @identifier ||= "#{index_name}:#{category_name}"
48
+ end
49
+
50
+ def to_s
51
+ "#{index_name} #{category_name}"
46
52
  end
47
53
 
48
54
  def self.index_root
File without changes
File without changes
@@ -0,0 +1,154 @@
1
+ require 'rack/mount'
2
+
3
+ module Internals
4
+
5
+ module FrontendAdapters
6
+
7
+ # TODO Rename to Routing again. Push everything back into appropriate Adapters.
8
+ #
9
+ class Rack # :nodoc:all
10
+
11
+ @@defaults = {
12
+ query_key: 'query'.freeze,
13
+ offset_key: 'offset'.freeze,
14
+ content_type: 'application/octet-stream'.freeze # TODO Wrong.
15
+ }
16
+
17
+ def initialize
18
+ @defaults = @@defaults.dup
19
+ end
20
+
21
+ #
22
+ #
23
+ def reset_routes
24
+ @routes = ::Rack::Mount::RouteSet.new
25
+ end
26
+ def routes
27
+ @routes || reset_routes
28
+ end
29
+ def finalize
30
+ routes.freeze
31
+ end
32
+
33
+ # Routing simply delegates to the route set to handle a request.
34
+ #
35
+ def call env
36
+ routes.call env
37
+ end
38
+
39
+ # API method.
40
+ #
41
+ def route options = {}
42
+ mappings, route_options = split options
43
+ mappings.each do |url, query|
44
+ route_one url, query, route_options
45
+ end
46
+ end
47
+ # Splits the route method options
48
+ # into real options and route options (/regexp/ => thing or 'some/path' => thing).
49
+ #
50
+ def split options
51
+ mappings = {}
52
+ route_options = {}
53
+ options.each_pair do |key, value|
54
+ if Regexp === key or String === key
55
+ mappings[key] = value
56
+ else
57
+ route_options[key] = value
58
+ end
59
+ end
60
+ [mappings, route_options]
61
+ end
62
+ def route_one url, query, route_options = {}
63
+ raise RouteTargetNilError.new(url) unless query
64
+ routes.add_route Internals::Adapters::Rack.app_for(query, route_options), default_options(url, route_options)
65
+ end
66
+ class RouteTargetNilError < StandardError
67
+ def initialize url
68
+ @url = url
69
+ end
70
+ def to_s
71
+ "Routing for #{@url.inspect} was defined with a nil target object, i.e. #{@url.inspect} => nil."
72
+ end
73
+ end
74
+ #
75
+ #
76
+ def root status
77
+ answer %r{^/$}, STATUSES[status]
78
+ end
79
+ #
80
+ #
81
+ def default status
82
+ answer nil, STATUSES[status]
83
+ end
84
+
85
+
86
+
87
+ # TODO Can Rack handle this for me?
88
+ #
89
+ # Note: Rack-mount already handles the 404.
90
+ #
91
+ STATUSES = {
92
+ 200 => lambda { |_| [200, { 'Content-Type' => 'text/html', 'Content-Length' => '0' }, ['']] },
93
+ 404 => lambda { |_| [404, { 'Content-Type' => 'text/html', 'Content-Length' => '0' }, ['']] }
94
+ }
95
+
96
+ #
97
+ #
98
+ def default_options url, route_options = {}
99
+ url = normalized url
100
+
101
+ options = { request_method: 'GET' }.merge route_options
102
+
103
+ options[:path_info] = url if url
104
+
105
+ options.delete :content_type
106
+
107
+ query_params = options.delete :query
108
+ options[:query_string] = %r{#{generate_query_string(query_params)}} if query_params
109
+
110
+ options
111
+ end
112
+ #
113
+ #
114
+ def generate_query_string query_params
115
+ raise "At least one query string condition is needed." if query_params.size.zero?
116
+ raise "Too many query param conditions (only 1 allowed): #{query_params}" if query_params.size > 1
117
+ k, v = query_params.first
118
+ "#{k}=#{v}"
119
+ end
120
+
121
+ # Setup a route that answers using the given app.
122
+ #
123
+ def answer url = nil, app = nil
124
+ routes.add_route (app || STATUSES[200]), default_options(url)
125
+ end
126
+
127
+ # Returns a regular expression for the url if it is given a String-like object.
128
+ #
129
+ def normalized url
130
+ url.respond_to?(:to_str) ? %r{#{url}} : url
131
+ end
132
+
133
+ # Returns true if there are no routes defined.
134
+ #
135
+ def empty?
136
+ routes.length.zero?
137
+ end
138
+
139
+ # TODO Beautify.
140
+ #
141
+ def to_s
142
+ routes.instance_variable_get(:@routes).map do |route|
143
+ path_info = route.conditions[:path_info]
144
+ anchored = ::Rack::Mount::Utils.regexp_anchored?(path_info)
145
+ anchored_ok = anchored ? "\u2713" : " "
146
+ "#{anchored_ok} #{path_info.source}"
147
+ end.join "\n"
148
+ end
149
+
150
+ end
151
+
152
+ end
153
+
154
+ end
@@ -0,0 +1,19 @@
1
+ module Internals
2
+
3
+ module Generators # :nodoc:all
4
+
5
+ # A cache generator holds an index.
6
+ #
7
+ class Base
8
+
9
+ attr_reader :index
10
+
11
+ def initialize index
12
+ @index = index
13
+ end
14
+
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,7 @@
1
+ module Internals
2
+ module Generators
3
+ module Partial
4
+ Default = Substring.new from: -3, to: -1
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,35 @@
1
+ module Internals
2
+
3
+ module Generators
4
+
5
+ module Partial
6
+
7
+ # Does not generate a partial index.
8
+ #
9
+ class None < Strategy
10
+
11
+ # Returns an empty index.
12
+ #
13
+ def generate_from index
14
+ {}
15
+ end
16
+
17
+ # Returns if this strategy's generated file is saved.
18
+ #
19
+ def saved?
20
+ false
21
+ end
22
+
23
+ # Do not use the partial bundle for getting ids and weights.
24
+ #
25
+ def use_exact_for_partial?
26
+ true
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,29 @@
1
+ module Internals
2
+
3
+ module Generators
4
+
5
+ module Partial
6
+
7
+ # Superclass for partial strategies.
8
+ #
9
+ class Strategy < Generators::Strategy
10
+
11
+ # Defines whether to use the exact bundle
12
+ # instead of the partial one.
13
+ #
14
+ # Default is @false@.
15
+ #
16
+ # For example:
17
+ # Partial::None.new # Uses the exact index instead of the partial one.
18
+ #
19
+ def use_exact_for_partial?
20
+ false
21
+ end
22
+
23
+ end
24
+
25
+ end
26
+
27
+ end
28
+
29
+ end
@@ -0,0 +1,122 @@
1
+ module Internals
2
+
3
+ module Generators
4
+
5
+ module Partial
6
+
7
+ # Generates the right substrings for use in the substring strategy.
8
+ #
9
+ class SubstringGenerator
10
+
11
+ attr_reader :from, :to
12
+
13
+ def initialize from, to
14
+ @from, @to = from, to
15
+
16
+ if @to.zero?
17
+ def each_subtoken token, &block
18
+ token.each_subtoken @from, &block
19
+ end
20
+ else
21
+ def each_subtoken token, &block
22
+ token[0..@to].intern.each_subtoken @from, &block
23
+ end
24
+ end
25
+
26
+ end
27
+
28
+ end
29
+
30
+ # The subtoken partial strategy.
31
+ #
32
+ # If given "florian"
33
+ # it will index "floria", "flori", "flor", "flo", "fl", "f"
34
+ # (Depending on what the given from value is, the example is with option from: 1)
35
+ #
36
+ class Substring < Strategy
37
+
38
+ # The from option signifies where in the symbol it
39
+ # will start in generating the subtokens.
40
+ #
41
+ # Examples:
42
+ #
43
+ # With :hello, and to: -1 (default)
44
+ # * from: 1 # => [:hello, :hell, :hel, :he, :h]
45
+ # * from: 4 # => [:hello, :hell]
46
+ #
47
+ # With :hello, and to: -2
48
+ # * from: 1 # => [:hell, :hel, :he, :h]
49
+ # * from: 4 # => [:hell]
50
+ #
51
+ def initialize options = {}
52
+ from = options[:from] || 1
53
+ to = options[:to] || -1
54
+ @generator = SubstringGenerator.new from, to
55
+ end
56
+
57
+ # Delegator to generator#from.
58
+ #
59
+ def from
60
+ @generator.from
61
+ end
62
+
63
+ # Delegator to generator#to.
64
+ #
65
+ def to
66
+ @generator.to
67
+ end
68
+
69
+ # Generates a partial index from the given index.
70
+ #
71
+ def generate_from index
72
+ result = {}
73
+
74
+ # Generate for each key token the subtokens.
75
+ #
76
+ i = 0
77
+ index.each_key do |token|
78
+ i += 1
79
+ if i == 5000
80
+ timed_exclaim "Generating partial tokens for token #{token}. This appears every 5000 tokens."
81
+ i = 0
82
+ end
83
+ generate_for token, index, result
84
+ end
85
+
86
+ # Remove duplicate ids.
87
+ #
88
+ # THINK If it is unique for a subtoken, it is
89
+ # unique for all derived longer tokens.
90
+ #
91
+ result.each_value &:uniq!
92
+
93
+ result
94
+ end
95
+
96
+ private
97
+
98
+ # To each shortened token of :test
99
+ # :test, :tes, :te, :t
100
+ # add all ids of :test
101
+ #
102
+ # "token" here means just text.
103
+ #
104
+ # THINK Could be improved by appending the aforegoing ids?
105
+ #
106
+ def generate_for token, index, result
107
+ @generator.each_subtoken(token) do |subtoken|
108
+ if result[subtoken]
109
+ result[subtoken] += index[token] # unique
110
+ else
111
+ result[subtoken] = index[token].dup
112
+ end
113
+ end
114
+ end
115
+
116
+ end
117
+
118
+ end
119
+
120
+ end
121
+
122
+ end
@@ -0,0 +1,19 @@
1
+ module Internals
2
+
3
+ module Generators
4
+
5
+ # The partial generator uses a subtoken(downto:1) generator as default.
6
+ #
7
+ class PartialGenerator < Base
8
+
9
+ # Generate a partial index based on the given index.
10
+ #
11
+ def generate strategy = Partial::Substring.new(from: 1)
12
+ strategy.generate_from self.index
13
+ end
14
+
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,9 @@
1
+ module Internals
2
+ module Generators
3
+ module Similarity
4
+ # Default is no similarity.
5
+ #
6
+ Default = None.new
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,81 @@
1
+ # encoding: utf-8
2
+ #
3
+ module Internals
4
+
5
+ module Generators
6
+
7
+ module Similarity
8
+
9
+ # DoubleLevensthone means that it's a combination of
10
+ # * DoubleMetaphone
11
+ # and
12
+ # * Levenshtein
13
+ # :)
14
+ #
15
+ class DoubleLevenshtone < Strategy
16
+
17
+ attr_reader :amount
18
+
19
+ #
20
+ #
21
+ def initialize amount = 10
22
+ @amount = amount
23
+ end
24
+
25
+ # Encodes the given symbol.
26
+ #
27
+ # Returns a symbol.
28
+ #
29
+ def encoded sym
30
+ codes = Text::Metaphone.double_metaphone sym.to_s
31
+ codes.first.to_sym unless codes.empty?
32
+ end
33
+
34
+ # Generates an index for the given index (in exact index style).
35
+ #
36
+ # In the following form:
37
+ # [:meier, :mueller, :peter, :pater] => { MR: [:meier], MLR: [:mueller], PTR: [:peter, :pater] }
38
+ #
39
+ def generate_from index
40
+ hash = hashify index.keys
41
+ sort hash
42
+ end
43
+
44
+ private
45
+
46
+ # Sorts the index values in place.
47
+ #
48
+ def sort index
49
+ index.each_pair.each do |code, ary|
50
+ ary.sort_by_levenshtein! code
51
+ ary.slice! amount, ary.size # size is not perfectly correct, but anyway
52
+ end
53
+ index
54
+ end
55
+
56
+ # Hashifies a list of symbols.
57
+ #
58
+ # Where:
59
+ # { encoded_sym => [syms] }
60
+ #
61
+ def hashify list
62
+ list.inject({}) do |total, element|
63
+ if code = encoded(element)
64
+ total[code] ||= []
65
+ total[code] << element
66
+ end
67
+ total
68
+ end
69
+ end
70
+
71
+ end
72
+
73
+ # ... aka Phonetic.
74
+ #
75
+ Phonetic = DoubleLevenshtone
76
+
77
+ end
78
+
79
+ end
80
+
81
+ end
@@ -0,0 +1,35 @@
1
+ module Internals
2
+
3
+ module Generators
4
+
5
+ module Similarity
6
+
7
+ # Similarity strategy that does nothing.
8
+ #
9
+ class None < Strategy
10
+
11
+ # Does not encode text. Just returns nil.
12
+ #
13
+ def encoded text
14
+ nil
15
+ end
16
+
17
+ # Returns an empty index.
18
+ #
19
+ def generate_from index
20
+ {}
21
+ end
22
+
23
+ # Returns if this strategy's generated file is saved.
24
+ #
25
+ def saved?
26
+ false
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,11 @@
1
+ module Internals
2
+ module Generators
3
+ module Similarity
4
+ # Base class for all similarity strategies.
5
+ #
6
+ class Strategy < Generators::Strategy
7
+
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ module Internals
2
+
3
+ module Generators
4
+
5
+ # Uses no similarity as default.
6
+ #
7
+ class SimilarityGenerator < Base
8
+
9
+ # Generate a similarity index based on the given index.
10
+ #
11
+ def generate strategy = Similarity::None.new
12
+ strategy.generate_from self.index
13
+ end
14
+
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,18 @@
1
+ module Internals
2
+
3
+ module Generators
4
+
5
+ class Strategy
6
+
7
+ # By default, all caches are saved in a
8
+ # storage (like a file).
9
+ #
10
+ def saved?
11
+ true
12
+ end
13
+
14
+ end
15
+
16
+ end
17
+
18
+ end
@@ -0,0 +1,9 @@
1
+ module Internals
2
+ module Generators
3
+ module Weights
4
+ # Default is Logarithmic.
5
+ #
6
+ Default = Logarithmic.new
7
+ end
8
+ end
9
+ end