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.
- data/lib/picky/{alias_instances.rb → aliases.rb} +1 -3
- data/lib/picky/application.rb +18 -19
- data/lib/picky/cores.rb +1 -1
- data/lib/picky/generators/aliases.rb +3 -0
- data/lib/picky/index/base.rb +179 -0
- data/lib/picky/index/memory.rb +28 -0
- data/lib/picky/index/redis.rb +28 -0
- data/lib/picky/{indexes_api.rb → index_bundle.rb} +16 -16
- data/lib/picky/indexed/indexes.rb +11 -7
- data/lib/picky/indexing/indexes.rb +14 -8
- data/lib/picky/internals/adapters/rack/base.rb +27 -0
- data/lib/picky/internals/adapters/rack/live_parameters.rb +37 -0
- data/lib/picky/internals/adapters/rack/query.rb +63 -0
- data/lib/picky/internals/adapters/rack.rb +34 -0
- data/lib/picky/{calculations → internals/calculations}/location.rb +0 -0
- data/lib/picky/{cli.rb → internals/cli.rb} +0 -0
- data/lib/picky/{configuration → internals/configuration}/index.rb +8 -2
- data/lib/picky/{ext → internals/ext}/maybe_compile.rb +0 -0
- data/lib/picky/{ext → internals/ext}/ruby19/extconf.rb +0 -0
- data/lib/picky/{ext → internals/ext}/ruby19/performant.c +0 -0
- data/lib/picky/{extensions → internals/extensions}/array.rb +0 -0
- data/lib/picky/{extensions → internals/extensions}/hash.rb +0 -0
- data/lib/picky/{extensions → internals/extensions}/module.rb +0 -0
- data/lib/picky/{extensions → internals/extensions}/object.rb +0 -0
- data/lib/picky/{extensions → internals/extensions}/symbol.rb +0 -0
- data/lib/picky/internals/frontend_adapters/rack.rb +154 -0
- data/lib/picky/internals/generators/base.rb +19 -0
- data/lib/picky/internals/generators/partial/default.rb +7 -0
- data/lib/picky/internals/generators/partial/none.rb +35 -0
- data/lib/picky/internals/generators/partial/strategy.rb +29 -0
- data/lib/picky/internals/generators/partial/substring.rb +122 -0
- data/lib/picky/internals/generators/partial_generator.rb +19 -0
- data/lib/picky/internals/generators/similarity/default.rb +9 -0
- data/lib/picky/internals/generators/similarity/double_levenshtone.rb +81 -0
- data/lib/picky/internals/generators/similarity/none.rb +35 -0
- data/lib/picky/internals/generators/similarity/strategy.rb +11 -0
- data/lib/picky/internals/generators/similarity_generator.rb +19 -0
- data/lib/picky/internals/generators/strategy.rb +18 -0
- data/lib/picky/internals/generators/weights/default.rb +9 -0
- data/lib/picky/internals/generators/weights/logarithmic.rb +43 -0
- data/lib/picky/internals/generators/weights/strategy.rb +11 -0
- data/lib/picky/internals/generators/weights_generator.rb +19 -0
- data/lib/picky/{helpers → internals/helpers}/measuring.rb +0 -0
- data/lib/picky/internals/index/backend.rb +113 -0
- data/lib/picky/internals/index/file/basic.rb +101 -0
- data/lib/picky/internals/index/file/json.rb +38 -0
- data/lib/picky/internals/index/file/marshal.rb +38 -0
- data/lib/picky/internals/index/file/text.rb +60 -0
- data/lib/picky/internals/index/files.rb +24 -0
- data/lib/picky/internals/index/redis/basic.rb +77 -0
- data/lib/picky/internals/index/redis/list_hash.rb +46 -0
- data/lib/picky/internals/index/redis/string_hash.rb +35 -0
- data/lib/picky/internals/index/redis.rb +44 -0
- data/lib/picky/internals/indexed/bundle/base.rb +72 -0
- data/lib/picky/internals/indexed/bundle/memory.rb +69 -0
- data/lib/picky/internals/indexed/bundle/redis.rb +70 -0
- data/lib/picky/internals/indexed/categories.rb +135 -0
- data/lib/picky/internals/indexed/category.rb +90 -0
- data/lib/picky/internals/indexed/index.rb +57 -0
- data/lib/picky/{indexed → internals/indexed}/wrappers/bundle/calculation.rb +0 -0
- data/lib/picky/{indexed → internals/indexed}/wrappers/bundle/location.rb +4 -2
- data/lib/picky/{indexed → internals/indexed}/wrappers/bundle/wrapper.rb +1 -1
- data/lib/picky/internals/indexed/wrappers/exact_first.rb +65 -0
- data/lib/picky/{indexers → internals/indexers}/no_source_specified_error.rb +0 -0
- data/lib/picky/{indexers → internals/indexers}/serial.rb +2 -2
- data/lib/picky/{indexers → internals/indexers}/solr.rb +0 -0
- data/lib/picky/internals/indexing/bundle/base.rb +219 -0
- data/lib/picky/internals/indexing/bundle/memory.rb +25 -0
- data/lib/picky/internals/indexing/bundle/redis.rb +28 -0
- data/lib/picky/internals/indexing/bundle/super_base.rb +65 -0
- data/lib/picky/internals/indexing/categories.rb +42 -0
- data/lib/picky/internals/indexing/category.rb +120 -0
- data/lib/picky/internals/indexing/index.rb +67 -0
- data/lib/picky/{performant.rb → internals/performant.rb} +0 -0
- data/lib/picky/internals/query/allocation.rb +88 -0
- data/lib/picky/internals/query/allocations.rb +137 -0
- data/lib/picky/internals/query/combination.rb +80 -0
- data/lib/picky/internals/query/combinations/base.rb +84 -0
- data/lib/picky/internals/query/combinations/memory.rb +58 -0
- data/lib/picky/internals/query/combinations/redis.rb +59 -0
- data/lib/picky/internals/query/indexes.rb +180 -0
- data/lib/picky/internals/query/qualifiers.rb +81 -0
- data/lib/picky/internals/query/token.rb +215 -0
- data/lib/picky/internals/query/tokens.rb +89 -0
- data/lib/picky/{query → internals/query}/weights.rb +0 -0
- data/lib/picky/internals/results/base.rb +106 -0
- data/lib/picky/internals/results/full.rb +17 -0
- data/lib/picky/internals/results/live.rb +17 -0
- data/lib/picky/{solr → internals/solr}/schema_generator.rb +0 -0
- data/lib/picky/internals/tokenizers/base.rb +166 -0
- data/lib/picky/internals/tokenizers/index.rb +63 -0
- data/lib/picky/internals/tokenizers/query.rb +79 -0
- data/lib/picky/loader.rb +148 -112
- data/lib/picky/query/base.rb +57 -26
- data/lib/picky/query/full.rb +1 -1
- data/lib/picky/query/live.rb +1 -1
- data/lib/picky/sources/db.rb +27 -6
- data/lib/tasks/index.rake +3 -3
- data/lib/tasks/try.rake +2 -2
- data/spec/lib/aliases_spec.rb +9 -0
- data/spec/lib/application_spec.rb +3 -3
- data/spec/lib/generators/aliases_spec.rb +1 -0
- data/spec/lib/{index_api_spec.rb → index/base_spec.rb} +7 -7
- data/spec/lib/index_bundle_spec.rb +71 -0
- data/spec/lib/indexed/indexes_spec.rb +61 -0
- data/spec/lib/indexing/indexes_spec.rb +94 -24
- data/spec/lib/{adapters → internals/adapters}/rack/base_spec.rb +2 -2
- data/spec/lib/{adapters → internals/adapters}/rack/live_parameters_spec.rb +2 -2
- data/spec/lib/{adapters → internals/adapters}/rack/query_spec.rb +2 -2
- data/spec/lib/{calculations → internals/calculations}/location_spec.rb +0 -0
- data/spec/lib/{cli_spec.rb → internals/cli_spec.rb} +4 -1
- data/spec/lib/{configuration → internals/configuration}/index_spec.rb +1 -1
- data/spec/lib/{cores_spec.rb → internals/cores_spec.rb} +0 -0
- data/spec/lib/{extensions → internals/extensions}/array_spec.rb +0 -0
- data/spec/lib/{extensions → internals/extensions}/hash_spec.rb +0 -0
- data/spec/lib/{extensions → internals/extensions}/module_spec.rb +0 -0
- data/spec/lib/{extensions → internals/extensions}/object_spec.rb +0 -0
- data/spec/lib/{extensions → internals/extensions}/symbol_spec.rb +0 -0
- data/spec/lib/{frontend_adapters → internals/frontend_adapters}/rack_spec.rb +11 -11
- data/spec/lib/{cacher → internals/generators}/cacher_strategy_spec.rb +2 -2
- data/spec/lib/internals/generators/partial/default_spec.rb +17 -0
- data/spec/lib/internals/generators/partial/none_spec.rb +17 -0
- data/spec/lib/{cacher → internals/generators}/partial/substring_spec.rb +26 -27
- data/spec/lib/{cacher → internals/generators}/partial_generator_spec.rb +5 -5
- data/spec/lib/{cacher → internals/generators}/similarity/double_levenshtone_spec.rb +4 -4
- data/spec/lib/{cacher → internals/generators}/similarity/none_spec.rb +2 -2
- data/spec/lib/{cacher → internals/generators}/similarity_generator_spec.rb +4 -4
- data/spec/lib/{cacher → internals/generators}/weights/logarithmic_spec.rb +2 -2
- data/spec/lib/internals/generators/weights_generator_spec.rb +21 -0
- data/spec/lib/{helpers → internals/helpers}/measuring_spec.rb +0 -0
- data/spec/lib/{index → internals/index}/file/basic_spec.rb +2 -2
- data/spec/lib/{index → internals/index}/file/json_spec.rb +2 -2
- data/spec/lib/{index → internals/index}/file/marshal_spec.rb +2 -2
- data/spec/lib/{index → internals/index}/file/text_spec.rb +2 -2
- data/spec/lib/{index → internals/index}/files_spec.rb +2 -2
- data/spec/lib/{indexed/bundle_spec.rb → internals/indexed/bundle/memory_spec.rb} +4 -5
- data/spec/lib/{indexed → internals/indexed}/categories_spec.rb +13 -13
- data/spec/lib/{indexed → internals/indexed}/category_spec.rb +59 -32
- data/spec/lib/{indexed → internals/indexed}/index_spec.rb +5 -5
- data/spec/lib/{indexed → internals/indexed}/wrappers/bundle/calculation_spec.rb +0 -0
- data/spec/lib/{indexed → internals/indexed}/wrappers/bundle/wrapper_spec.rb +0 -0
- data/spec/lib/{indexed → internals/indexed}/wrappers/exact_first_spec.rb +5 -5
- data/spec/lib/{indexers → internals/indexers}/serial_spec.rb +0 -0
- data/spec/lib/{indexing/bundle_partial_generation_speed_spec.rb → internals/indexing/bundle/memory_partial_generation_speed_spec.rb} +3 -3
- data/spec/lib/{indexing/bundle_spec.rb → internals/indexing/bundle/memory_spec.rb} +3 -3
- data/spec/lib/{index/bundle_spec.rb → internals/indexing/bundle/super_base_spec.rb} +9 -3
- data/spec/lib/{indexing → internals/indexing}/category_spec.rb +3 -3
- data/spec/lib/{indexing → internals/indexing}/index_spec.rb +3 -3
- data/spec/lib/internals/indexing/indexes_spec.rb +36 -0
- data/spec/lib/{interfaces → internals/interfaces}/live_parameters_spec.rb +0 -0
- data/spec/lib/internals/results/base_spec.rb +105 -0
- data/spec/lib/internals/results/full_spec.rb +78 -0
- data/spec/lib/internals/results/live_spec.rb +88 -0
- data/spec/lib/{solr → internals/solr}/schema_generator_spec.rb +0 -0
- data/spec/lib/{tokenizers → internals/tokenizers}/base_spec.rb +3 -3
- data/spec/lib/{tokenizers → internals/tokenizers}/index_spec.rb +9 -9
- data/spec/lib/{tokenizers → internals/tokenizers}/query_spec.rb +11 -11
- data/spec/lib/query/allocation_spec.rb +12 -12
- data/spec/lib/query/allocations_spec.rb +19 -19
- data/spec/lib/query/base_spec.rb +28 -4
- data/spec/lib/query/combination_spec.rb +8 -9
- data/spec/lib/query/combinations/base_spec.rb +116 -0
- data/spec/lib/query/{combinations_spec.rb → combinations/memory_spec.rb} +14 -14
- data/spec/lib/query/combinations/redis_spec.rb +132 -0
- data/spec/lib/query/full_spec.rb +2 -2
- data/spec/lib/query/indexes_spec.rb +81 -0
- data/spec/lib/query/live_spec.rb +3 -3
- data/spec/lib/query/qualifiers_spec.rb +6 -6
- data/spec/lib/query/token_spec.rb +38 -38
- data/spec/lib/query/tokens_spec.rb +35 -35
- data/spec/lib/sources/db_spec.rb +23 -18
- metadata +212 -181
- data/lib/picky/adapters/rack/base.rb +0 -23
- data/lib/picky/adapters/rack/live_parameters.rb +0 -33
- data/lib/picky/adapters/rack/query.rb +0 -59
- data/lib/picky/adapters/rack.rb +0 -28
- data/lib/picky/cacher/convenience.rb +0 -3
- data/lib/picky/cacher/generator.rb +0 -15
- data/lib/picky/cacher/partial/default.rb +0 -5
- data/lib/picky/cacher/partial/none.rb +0 -31
- data/lib/picky/cacher/partial/strategy.rb +0 -21
- data/lib/picky/cacher/partial/substring.rb +0 -118
- data/lib/picky/cacher/partial_generator.rb +0 -15
- data/lib/picky/cacher/similarity/default.rb +0 -7
- data/lib/picky/cacher/similarity/double_levenshtone.rb +0 -77
- data/lib/picky/cacher/similarity/none.rb +0 -31
- data/lib/picky/cacher/similarity/strategy.rb +0 -9
- data/lib/picky/cacher/similarity_generator.rb +0 -15
- data/lib/picky/cacher/strategy.rb +0 -12
- data/lib/picky/cacher/weights/default.rb +0 -7
- data/lib/picky/cacher/weights/logarithmic.rb +0 -39
- data/lib/picky/cacher/weights/strategy.rb +0 -9
- data/lib/picky/cacher/weights_generator.rb +0 -15
- data/lib/picky/frontend_adapters/rack.rb +0 -150
- data/lib/picky/index/bundle.rb +0 -54
- data/lib/picky/index/file/basic.rb +0 -97
- data/lib/picky/index/file/json.rb +0 -34
- data/lib/picky/index/file/marshal.rb +0 -34
- data/lib/picky/index/file/text.rb +0 -56
- data/lib/picky/index/files.rb +0 -118
- data/lib/picky/index_api.rb +0 -175
- data/lib/picky/indexed/bundle.rb +0 -54
- data/lib/picky/indexed/categories.rb +0 -131
- data/lib/picky/indexed/category.rb +0 -85
- data/lib/picky/indexed/index.rb +0 -39
- data/lib/picky/indexed/wrappers/exact_first.rb +0 -61
- data/lib/picky/indexing/bundle.rb +0 -213
- data/lib/picky/indexing/categories.rb +0 -38
- data/lib/picky/indexing/category.rb +0 -117
- data/lib/picky/indexing/index.rb +0 -55
- data/lib/picky/query/allocation.rb +0 -82
- data/lib/picky/query/allocations.rb +0 -130
- data/lib/picky/query/combination.rb +0 -74
- data/lib/picky/query/combinations.rb +0 -105
- data/lib/picky/query/qualifiers.rb +0 -77
- data/lib/picky/query/token.rb +0 -202
- data/lib/picky/query/tokens.rb +0 -86
- data/lib/picky/query/weigher.rb +0 -165
- data/lib/picky/results/base.rb +0 -102
- data/lib/picky/results/full.rb +0 -13
- data/lib/picky/results/live.rb +0 -13
- data/lib/picky/tokenizers/base.rb +0 -161
- data/lib/picky/tokenizers/index.rb +0 -58
- data/lib/picky/tokenizers/query.rb +0 -74
- data/spec/lib/cacher/partial/default_spec.rb +0 -15
- data/spec/lib/cacher/partial/none_spec.rb +0 -17
- data/spec/lib/cacher/weights_generator_spec.rb +0 -21
- data/spec/lib/results/base_spec.rb +0 -257
- 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
|
|
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}
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
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,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,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,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
|