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