picky 2.6.0 → 2.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/picky/analyzer.rb +4 -4
- data/lib/picky/application.rb +6 -7
- data/lib/picky/backend/{backend.rb → base.rb} +31 -14
- data/lib/picky/backend/file/basic.rb +12 -4
- data/lib/picky/backend/file/json.rb +5 -5
- data/lib/picky/backend/file/text.rb +1 -1
- data/lib/picky/backend/files.rb +3 -9
- data/lib/picky/backend/redis/basic.rb +8 -0
- data/lib/picky/backend/redis/list_hash.rb +5 -5
- data/lib/picky/backend/redis/string_hash.rb +5 -5
- data/lib/picky/backend/redis.rb +5 -5
- data/lib/picky/bundle.rb +62 -0
- data/lib/picky/categories.rb +10 -9
- data/lib/picky/categories_indexed.rb +12 -7
- data/lib/picky/categories_indexing.rb +7 -9
- data/lib/picky/category.rb +38 -26
- data/lib/picky/category_indexed.rb +4 -20
- data/lib/picky/category_indexing.rb +71 -68
- data/lib/picky/generators/base.rb +6 -6
- data/lib/picky/generators/partial/substring.rb +28 -26
- data/lib/picky/generators/partial_generator.rb +3 -3
- data/lib/picky/generators/similarity/phonetic.rb +5 -5
- data/lib/picky/generators/similarity_generator.rb +2 -2
- data/lib/picky/generators/weights/logarithmic.rb +3 -3
- data/lib/picky/generators/weights_generator.rb +2 -2
- data/lib/picky/index/base.rb +13 -10
- data/lib/picky/index/base_indexed.rb +2 -0
- data/lib/picky/index/base_indexing.rb +65 -57
- data/lib/picky/indexed/bundle/base.rb +21 -86
- data/lib/picky/indexed/bundle/memory.rb +5 -12
- data/lib/picky/indexed/bundle/redis.rb +42 -0
- data/lib/picky/indexed/wrappers/bundle/wrapper.rb +3 -3
- data/lib/picky/indexers/base.rb +20 -3
- data/lib/picky/indexers/parallel.rb +32 -14
- data/lib/picky/indexers/serial.rb +29 -26
- data/lib/picky/indexes.rb +5 -3
- data/lib/picky/indexes_indexed.rb +3 -15
- data/lib/picky/indexes_indexing.rb +18 -21
- data/lib/picky/indexing/bundle/base.rb +64 -45
- data/lib/picky/indexing/bundle/memory.rb +0 -4
- data/lib/picky/loader.rb +7 -6
- data/lib/picky/query/allocation.rb +3 -3
- data/lib/picky/query/token.rb +5 -1
- data/lib/picky/search.rb +5 -0
- data/lib/picky/sources/base.rb +21 -2
- data/lib/picky/sources/db.rb +0 -7
- data/lib/picky/statistics.rb +9 -12
- data/lib/picky/tokenizers/location.rb +1 -1
- data/lib/tasks/checks.rake +8 -6
- data/lib/tasks/index.rake +14 -20
- data/lib/tasks/server.rake +18 -2
- data/lib/tasks/statistics.rake +27 -14
- data/lib/tasks/todo.rake +2 -2
- data/lib/tasks/try.rake +12 -27
- data/spec/lib/application_spec.rb +1 -1
- data/spec/lib/backend/file/basic_spec.rb +6 -6
- data/spec/lib/backend/file/json_spec.rb +11 -6
- data/spec/lib/backend/file/marshal_spec.rb +11 -6
- data/spec/lib/backend/files_spec.rb +21 -7
- data/spec/lib/backend/redis/basic_spec.rb +6 -0
- data/spec/lib/backend/redis/list_hash_spec.rb +9 -3
- data/spec/lib/backend/redis/string_hash_spec.rb +7 -1
- data/spec/lib/backend/redis_spec.rb +22 -12
- data/spec/lib/categories_indexed_spec.rb +2 -2
- data/spec/lib/category_indexing_spec.rb +12 -33
- data/spec/lib/category_spec.rb +22 -0
- data/spec/lib/index/base_indexing_spec.rb +30 -0
- data/spec/lib/indexed/bundle/memory_spec.rb +13 -20
- data/spec/lib/indexers/base_spec.rb +39 -4
- data/spec/lib/indexers/parallel_spec.rb +2 -10
- data/spec/lib/indexers/serial_spec.rb +11 -26
- data/spec/lib/indexes_class_spec.rb +4 -4
- data/spec/lib/indexes_indexed_spec.rb +2 -2
- data/spec/lib/indexes_indexing_spec.rb +6 -10
- data/spec/lib/indexes_spec.rb +3 -3
- data/spec/lib/indexing/bundle/{super_base_spec.rb → base_spec.rb} +2 -2
- data/spec/lib/indexing/bundle/memory_partial_generation_speed_spec.rb +3 -3
- data/spec/lib/indexing/bundle/memory_spec.rb +16 -14
- data/spec/lib/indexing/bundle/redis_spec.rb +18 -16
- data/spec/lib/query/allocation_spec.rb +1 -1
- data/spec/lib/query/token_spec.rb +5 -7
- data/spec/lib/sources/base_spec.rb +53 -0
- data/spec/lib/sources/db_spec.rb +0 -7
- metadata +11 -12
- data/lib/picky/indexers/solr.rb +0 -56
- data/lib/picky/indexing/bundle/super_base.rb +0 -61
- data/lib/picky/solr/schema_generator.rb +0 -74
- data/lib/tasks/search.rake +0 -9
- data/lib/tasks/shortcuts.rake +0 -32
- data/lib/tasks/solr.rake +0 -36
data/lib/picky/analyzer.rb
CHANGED
@@ -17,11 +17,11 @@ class Analyzer # :nodoc:all
|
|
17
17
|
#
|
18
18
|
#
|
19
19
|
def analyze bundle
|
20
|
-
bundle.
|
21
|
-
analysis[:__keys] = bundle.size
|
22
|
-
cardinality :index, bundle.
|
20
|
+
bundle.load_inverted
|
21
|
+
analysis[:__keys] = bundle.inverted.size
|
22
|
+
cardinality :index, bundle.inverted
|
23
23
|
index_analysis
|
24
|
-
bundle.
|
24
|
+
bundle.clear_inverted
|
25
25
|
|
26
26
|
bundle.load_weights
|
27
27
|
weights bundle.weights
|
data/lib/picky/application.rb
CHANGED
@@ -68,7 +68,7 @@
|
|
68
68
|
# In full glory:
|
69
69
|
# class MyGreatSearch < Application
|
70
70
|
#
|
71
|
-
# books =
|
71
|
+
# books = Index::Memory.new :books do
|
72
72
|
# source Sources::CSV.new(:title, :author, :isbn, file:'app/library.csv')
|
73
73
|
# category :title
|
74
74
|
# end
|
@@ -227,12 +227,6 @@ class Application
|
|
227
227
|
"WARNING: No routes defined for application configuration in #{self.class}." if rack_adapter.empty?
|
228
228
|
end
|
229
229
|
|
230
|
-
def to_s # :nodoc:
|
231
|
-
<<-APPLICATION
|
232
|
-
\033[1m#{name}\033[m
|
233
|
-
#{to_stats.indented_to_s}
|
234
|
-
APPLICATION
|
235
|
-
end
|
236
230
|
def to_stats
|
237
231
|
<<-APP
|
238
232
|
\033[1mIndexing (default)\033[m:
|
@@ -248,10 +242,15 @@ APPLICATION
|
|
248
242
|
#{to_routes.indented_to_s}
|
249
243
|
APP
|
250
244
|
end
|
245
|
+
|
251
246
|
def to_routes
|
252
247
|
rack_adapter.to_s
|
253
248
|
end
|
254
249
|
|
250
|
+
def to_s # :nodoc:
|
251
|
+
self.name
|
252
|
+
end
|
253
|
+
|
255
254
|
end
|
256
255
|
|
257
256
|
end
|
@@ -1,13 +1,20 @@
|
|
1
1
|
module Backend
|
2
2
|
|
3
|
-
class
|
3
|
+
class Base
|
4
4
|
|
5
|
-
attr_reader :bundle_name
|
6
|
-
|
5
|
+
attr_reader :bundle_name,
|
6
|
+
:prepared,
|
7
|
+
:inverted,
|
8
|
+
:weights,
|
9
|
+
:similarity,
|
10
|
+
:configuration,
|
11
|
+
:category,
|
12
|
+
:identifier
|
7
13
|
|
8
14
|
delegate :index_name, :category_name, :to => :@category
|
9
15
|
|
10
16
|
def initialize bundle_name, category
|
17
|
+
@identifier = "#{category.identifier}:#{bundle_name}"
|
11
18
|
@bundle_name = bundle_name
|
12
19
|
@category = category
|
13
20
|
@prepared = File::Text.new category.prepared_index_path
|
@@ -24,23 +31,27 @@ module Backend
|
|
24
31
|
|
25
32
|
# Dumping.
|
26
33
|
#
|
27
|
-
def
|
28
|
-
|
34
|
+
def dump_inverted inverted_hash
|
35
|
+
timed_exclaim %Q{"#{identifier}": => #{inverted}.}
|
36
|
+
inverted.dump inverted_hash
|
29
37
|
end
|
30
38
|
def dump_weights weights_hash
|
39
|
+
timed_exclaim %Q{"#{identifier}": => #{weights}.}
|
31
40
|
weights.dump weights_hash
|
32
41
|
end
|
33
42
|
def dump_similarity similarity_hash
|
43
|
+
timed_exclaim %Q{"#{identifier}": => #{similarity}.}
|
34
44
|
similarity.dump similarity_hash
|
35
45
|
end
|
36
46
|
def dump_configuration configuration_hash
|
47
|
+
timed_exclaim %Q{"#{identifier}": => #{configuration}.}
|
37
48
|
configuration.dump configuration_hash
|
38
49
|
end
|
39
50
|
|
40
51
|
# Loading.
|
41
52
|
#
|
42
|
-
def
|
43
|
-
|
53
|
+
def load_inverted
|
54
|
+
inverted.load
|
44
55
|
end
|
45
56
|
def load_similarity
|
46
57
|
similarity.load
|
@@ -54,8 +65,8 @@ module Backend
|
|
54
65
|
|
55
66
|
# Cache ok?
|
56
67
|
#
|
57
|
-
def
|
58
|
-
|
68
|
+
def inverted_cache_ok?
|
69
|
+
inverted.cache_ok?
|
59
70
|
end
|
60
71
|
def similarity_cache_ok?
|
61
72
|
similarity.cache_ok?
|
@@ -66,8 +77,8 @@ module Backend
|
|
66
77
|
|
67
78
|
# Cache small?
|
68
79
|
#
|
69
|
-
def
|
70
|
-
|
80
|
+
def inverted_cache_small?
|
81
|
+
inverted.cache_small?
|
71
82
|
end
|
72
83
|
def similarity_cache_small?
|
73
84
|
similarity.cache_small?
|
@@ -79,7 +90,7 @@ module Backend
|
|
79
90
|
# Copies the indexes to the "backup" directory.
|
80
91
|
#
|
81
92
|
def backup
|
82
|
-
|
93
|
+
inverted.backup
|
83
94
|
weights.backup
|
84
95
|
similarity.backup
|
85
96
|
configuration.backup
|
@@ -88,7 +99,7 @@ module Backend
|
|
88
99
|
# Restores the indexes from the "backup" directory.
|
89
100
|
#
|
90
101
|
def restore
|
91
|
-
|
102
|
+
inverted.restore
|
92
103
|
weights.restore
|
93
104
|
similarity.restore
|
94
105
|
configuration.restore
|
@@ -97,12 +108,18 @@ module Backend
|
|
97
108
|
# Delete all index files.
|
98
109
|
#
|
99
110
|
def delete
|
100
|
-
|
111
|
+
inverted.delete
|
101
112
|
weights.delete
|
102
113
|
similarity.delete
|
103
114
|
configuration.delete
|
104
115
|
end
|
105
116
|
|
117
|
+
#
|
118
|
+
#
|
119
|
+
def to_s
|
120
|
+
"#{self.class}(#{prepared}, #{bundle_name}, #{category.identifier})"
|
121
|
+
end
|
122
|
+
|
106
123
|
end
|
107
124
|
|
108
125
|
end
|
@@ -13,6 +13,8 @@ module Backend
|
|
13
13
|
#
|
14
14
|
class Basic
|
15
15
|
|
16
|
+
# This file's location.
|
17
|
+
#
|
16
18
|
attr_reader :cache_path
|
17
19
|
|
18
20
|
# An index cache takes a path, without file extension,
|
@@ -22,10 +24,6 @@ module Backend
|
|
22
24
|
@cache_path = "#{cache_path}.#{extension}"
|
23
25
|
end
|
24
26
|
|
25
|
-
def to_s
|
26
|
-
cache_path
|
27
|
-
end
|
28
|
-
|
29
27
|
# The default extension for index files is "index".
|
30
28
|
#
|
31
29
|
def extension
|
@@ -40,12 +38,15 @@ module Backend
|
|
40
38
|
prepare_backup backup_directory
|
41
39
|
FileUtils.cp cache_path, target, verbose: true
|
42
40
|
end
|
41
|
+
|
43
42
|
# The backup directory of this file.
|
44
43
|
# Equal to the file's dirname plus /backup
|
45
44
|
#
|
45
|
+
|
46
46
|
def backup_directory
|
47
47
|
::File.join ::File.dirname(cache_path), 'backup'
|
48
48
|
end
|
49
|
+
|
49
50
|
# Prepares the backup directory for the file.
|
50
51
|
#
|
51
52
|
def prepare_backup target
|
@@ -58,6 +59,7 @@ module Backend
|
|
58
59
|
def restore
|
59
60
|
FileUtils.cp backup_file_path_of(cache_path), cache_path, verbose: true
|
60
61
|
end
|
62
|
+
|
61
63
|
# The backup filename.
|
62
64
|
#
|
63
65
|
def backup_file_path_of path
|
@@ -94,6 +96,12 @@ module Backend
|
|
94
96
|
`ls -l #{path} | awk '{print $5}'`.to_i
|
95
97
|
end
|
96
98
|
|
99
|
+
#
|
100
|
+
#
|
101
|
+
def to_s
|
102
|
+
"#{self.class}(#{cache_path})"
|
103
|
+
end
|
104
|
+
|
97
105
|
end
|
98
106
|
|
99
107
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module Backend
|
2
|
-
|
2
|
+
|
3
3
|
module File
|
4
|
-
|
4
|
+
|
5
5
|
# Index files dumped in the JSON format.
|
6
6
|
#
|
7
7
|
class JSON < Basic
|
8
|
-
|
8
|
+
|
9
9
|
# Uses the extension "json".
|
10
10
|
#
|
11
11
|
def extension
|
@@ -26,9 +26,9 @@ module Backend
|
|
26
26
|
def retrieve
|
27
27
|
raise "Can't retrieve from JSON file. Use text file."
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
end
|
33
33
|
|
34
34
|
end
|
data/lib/picky/backend/files.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Backend
|
2
2
|
|
3
|
-
class Files <
|
3
|
+
class Files < Base
|
4
4
|
|
5
5
|
def initialize bundle_name, category
|
6
6
|
super bundle_name, category
|
@@ -9,20 +9,14 @@ module Backend
|
|
9
9
|
# Yajl json lib cannot load symbolized
|
10
10
|
# values, just keys.
|
11
11
|
#
|
12
|
-
@
|
12
|
+
@inverted = File::JSON.new category.index_path(bundle_name, :inverted)
|
13
13
|
@weights = File::JSON.new category.index_path(bundle_name, :weights)
|
14
14
|
@similarity = File::Marshal.new category.index_path(bundle_name, :similarity)
|
15
15
|
@configuration = File::JSON.new category.index_path(bundle_name, :configuration)
|
16
16
|
end
|
17
17
|
|
18
18
|
def to_s
|
19
|
-
|
20
|
-
Files:
|
21
|
-
#{"Index: #{@index}".indented_to_s}
|
22
|
-
#{"Weights: #{@weights}".indented_to_s}
|
23
|
-
#{"Similarity: #{@similarity}".indented_to_s}
|
24
|
-
#{"Config: #{@configuration}".indented_to_s}
|
25
|
-
FILES
|
19
|
+
"#{self.class}(#{[@prepared, @inverted, @weights, @similarity, @configuration].join(', ')})"
|
26
20
|
end
|
27
21
|
|
28
22
|
end
|
@@ -61,6 +61,7 @@ module Backend
|
|
61
61
|
def cache_small?
|
62
62
|
size < 1
|
63
63
|
end
|
64
|
+
|
64
65
|
# Is the cache ok?
|
65
66
|
#
|
66
67
|
# A small cache is still ok.
|
@@ -68,6 +69,7 @@ module Backend
|
|
68
69
|
def cache_ok?
|
69
70
|
size > 0
|
70
71
|
end
|
72
|
+
|
71
73
|
# Extracts the size of the file in Bytes.
|
72
74
|
#
|
73
75
|
# Note: This is a very forgiving implementation.
|
@@ -78,6 +80,12 @@ module Backend
|
|
78
80
|
backend.dbsize
|
79
81
|
end
|
80
82
|
|
83
|
+
#
|
84
|
+
#
|
85
|
+
def to_s
|
86
|
+
"#{self.class}(#{namespace}:*)"
|
87
|
+
end
|
88
|
+
|
81
89
|
end
|
82
90
|
|
83
91
|
end
|
@@ -17,7 +17,7 @@ module Backend
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
# Clear the index for this list.
|
22
22
|
#
|
23
23
|
# Note: Perhaps we can use a server only command.
|
@@ -32,14 +32,14 @@ module Backend
|
|
32
32
|
|
33
33
|
# Get a collection.
|
34
34
|
#
|
35
|
-
def collection
|
36
|
-
backend.
|
35
|
+
def collection key
|
36
|
+
backend.zrange "#{namespace}:#{key}", 0, -1
|
37
37
|
end
|
38
38
|
|
39
39
|
# Get a single value.
|
40
40
|
#
|
41
|
-
def member
|
42
|
-
raise "Can't retrieve
|
41
|
+
def member key
|
42
|
+
raise "Can't retrieve single value :#{key} from a Redis ListHash. Use Index::Redis::StringHash."
|
43
43
|
end
|
44
44
|
|
45
45
|
end
|
@@ -14,7 +14,7 @@ module Backend
|
|
14
14
|
backend.hset namespace, key, value
|
15
15
|
end
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
# Clears the hash.
|
19
19
|
#
|
20
20
|
def clear
|
@@ -23,14 +23,14 @@ module Backend
|
|
23
23
|
|
24
24
|
# Get a collection.
|
25
25
|
#
|
26
|
-
def collection
|
27
|
-
raise "Can't retrieve
|
26
|
+
def collection key
|
27
|
+
raise "Can't retrieve collection for :#{key} from a StringHash. Use Index::Redis::ListHash."
|
28
28
|
end
|
29
29
|
|
30
30
|
# Get a single value.
|
31
31
|
#
|
32
|
-
def member
|
33
|
-
backend.hget namespace,
|
32
|
+
def member key
|
33
|
+
backend.hget namespace, key
|
34
34
|
end
|
35
35
|
|
36
36
|
end
|
data/lib/picky/backend/redis.rb
CHANGED
@@ -1,24 +1,24 @@
|
|
1
1
|
module Backend
|
2
2
|
|
3
|
-
# TODO Needs a reconnect to be run after forking.
|
4
3
|
#
|
5
|
-
|
4
|
+
#
|
5
|
+
class Redis < Base
|
6
6
|
|
7
7
|
def initialize bundle_name, category
|
8
8
|
super bundle_name, category
|
9
9
|
|
10
10
|
# Refine a few Redis "types".
|
11
11
|
#
|
12
|
-
@
|
12
|
+
@inverted = Redis::ListHash.new "#{category.identifier}:#{bundle_name}:inverted"
|
13
13
|
@weights = Redis::StringHash.new "#{category.identifier}:#{bundle_name}:weights"
|
14
|
-
@similarity = Redis::ListHash.new
|
14
|
+
@similarity = Redis::ListHash.new "#{category.identifier}:#{bundle_name}:similarity"
|
15
15
|
@configuration = Redis::StringHash.new "#{category.identifier}:#{bundle_name}:configuration"
|
16
16
|
end
|
17
17
|
|
18
18
|
# Delegate to the right collection.
|
19
19
|
#
|
20
20
|
def ids sym
|
21
|
-
|
21
|
+
inverted.collection sym
|
22
22
|
end
|
23
23
|
|
24
24
|
# Delegate to the right member value.
|
data/lib/picky/bundle.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# A Bundle is a number of indexes
|
2
|
+
# per [index, category] combination.
|
3
|
+
#
|
4
|
+
# At most, there are three indexes:
|
5
|
+
# * *core* index (always used)
|
6
|
+
# * *weights* index (always used)
|
7
|
+
# * *similarity* index (used with similarity)
|
8
|
+
#
|
9
|
+
# In Picky, indexing is separated from the index
|
10
|
+
# handling itself through a parallel structure.
|
11
|
+
#
|
12
|
+
# Both use methods provided by this base class, but
|
13
|
+
# have very different goals:
|
14
|
+
#
|
15
|
+
# * *Indexing*::*Bundle*::*Base* is just concerned with creating index
|
16
|
+
# files / redis entries and providing helper functions to e.g. check
|
17
|
+
# the indexes.
|
18
|
+
#
|
19
|
+
# * *Index*::*Bundle*::*Base* is concerned with loading these index files into
|
20
|
+
# memory / redis and looking up search data as fast as possible.
|
21
|
+
#
|
22
|
+
class Bundle
|
23
|
+
|
24
|
+
attr_reader :identifier,
|
25
|
+
:files
|
26
|
+
attr_accessor :inverted,
|
27
|
+
:weights,
|
28
|
+
:similarity,
|
29
|
+
:configuration,
|
30
|
+
:similarity_strategy
|
31
|
+
|
32
|
+
delegate :clear, :to => :inverted
|
33
|
+
delegate :[], :[]=, :to => :configuration
|
34
|
+
|
35
|
+
def initialize name, category, similarity_strategy
|
36
|
+
@identifier = "#{category.identifier}:#{name}"
|
37
|
+
@files = Backend::Files.new name, category
|
38
|
+
|
39
|
+
@inverted = {}
|
40
|
+
@weights = {}
|
41
|
+
@similarity = {}
|
42
|
+
@configuration = {} # A hash with config options.
|
43
|
+
|
44
|
+
@similarity_strategy = similarity_strategy
|
45
|
+
end
|
46
|
+
|
47
|
+
# Get a list of similar texts.
|
48
|
+
#
|
49
|
+
# Note: Does not return itself.
|
50
|
+
#
|
51
|
+
def similar text
|
52
|
+
code = similarity_strategy.encoded text
|
53
|
+
similar_codes = code && @similarity[code]
|
54
|
+
similar_codes.delete text if similar_codes
|
55
|
+
similar_codes || []
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_s
|
59
|
+
"#{self.class}(#{identifier}, #{files})"
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
data/lib/picky/categories.rb
CHANGED
@@ -8,6 +8,7 @@ class Categories
|
|
8
8
|
:to => :categories
|
9
9
|
|
10
10
|
each_delegate :reindex,
|
11
|
+
:each_category,
|
11
12
|
:to => :categories
|
12
13
|
|
13
14
|
# A list of indexed categories.
|
@@ -26,18 +27,25 @@ class Categories
|
|
26
27
|
# Nifty! :)
|
27
28
|
#
|
28
29
|
def initialize options = {}
|
29
|
-
|
30
|
+
clear_categories
|
30
31
|
|
31
32
|
@ignore_unassigned_tokens = options[:ignore_unassigned_tokens] || false
|
32
33
|
end
|
33
34
|
|
34
35
|
# Clears both the array of categories and the hash of categories.
|
35
36
|
#
|
36
|
-
def
|
37
|
+
def clear_categories
|
37
38
|
@categories = []
|
38
39
|
@category_hash = {}
|
39
40
|
end
|
40
41
|
|
42
|
+
# Add the given category to the list of categories.
|
43
|
+
#
|
44
|
+
def << category
|
45
|
+
categories << category
|
46
|
+
category_hash[category.name] = category
|
47
|
+
end
|
48
|
+
|
41
49
|
# Find a given category in the categories.
|
42
50
|
#
|
43
51
|
def [] category_name
|
@@ -48,13 +56,6 @@ class Categories
|
|
48
56
|
raise %Q{Index category "#{category_name}" not found. Possible categories: "#{categories.map(&:name).join('", "')}".}
|
49
57
|
end
|
50
58
|
|
51
|
-
# Add the given category to the list of categories.
|
52
|
-
#
|
53
|
-
def << category
|
54
|
-
categories << category
|
55
|
-
category_hash[category.name] = category
|
56
|
-
end
|
57
|
-
|
58
59
|
def to_s
|
59
60
|
categories.join(', ')
|
60
61
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
class Categories
|
2
|
-
|
2
|
+
|
3
3
|
attr_reader :ignore_unassigned_tokens
|
4
4
|
|
5
5
|
each_delegate :load_from_cache,
|
@@ -15,17 +15,17 @@ class Categories
|
|
15
15
|
def possible_combinations_for token
|
16
16
|
token.similar? ? similar_possible_for(token) : possible_for(token)
|
17
17
|
end
|
18
|
+
|
18
19
|
# Gets all similar tokens and puts together the possible combinations
|
19
20
|
# for each found similar token.
|
20
21
|
#
|
21
22
|
def similar_possible_for token
|
22
|
-
# Get as many tokens as necessary
|
23
|
-
#
|
24
23
|
tokens = similar_tokens_for token
|
25
|
-
# possible combinations
|
26
|
-
#
|
27
24
|
inject_possible_for tokens
|
28
25
|
end
|
26
|
+
|
27
|
+
# Returns all possible similar tokens for the given token.
|
28
|
+
#
|
29
29
|
def similar_tokens_for token
|
30
30
|
text = token.text
|
31
31
|
categories.inject([]) do |result, category|
|
@@ -41,6 +41,9 @@ class Categories
|
|
41
41
|
result
|
42
42
|
end
|
43
43
|
end
|
44
|
+
|
45
|
+
#
|
46
|
+
#
|
44
47
|
def inject_possible_for tokens
|
45
48
|
tokens.inject([]) do |result, token|
|
46
49
|
possible = possible_categories token
|
@@ -65,8 +68,9 @@ class Categories
|
|
65
68
|
# This is an optimization to mark tokens that are ignored.
|
66
69
|
#
|
67
70
|
return if ignore_unassigned_tokens && possible.empty?
|
68
|
-
possible
|
71
|
+
possible
|
69
72
|
end
|
73
|
+
|
70
74
|
# This returns the possible categories for this token.
|
71
75
|
# If the user has already preselected a category for this token,
|
72
76
|
# like "artist:moby", if not just return all for the given token,
|
@@ -77,6 +81,7 @@ class Categories
|
|
77
81
|
def possible_categories token
|
78
82
|
user_defined_categories(token) || categories
|
79
83
|
end
|
84
|
+
|
80
85
|
# This returns the array of categories if the user has defined
|
81
86
|
# an existing category.
|
82
87
|
#
|
@@ -89,5 +94,5 @@ class Categories
|
|
89
94
|
category_hash[name]
|
90
95
|
end.compact
|
91
96
|
end
|
92
|
-
|
97
|
+
|
93
98
|
end
|
@@ -1,12 +1,10 @@
|
|
1
1
|
class Categories
|
2
|
-
|
3
|
-
each_delegate :
|
4
|
-
:
|
5
|
-
:
|
6
|
-
:
|
7
|
-
:
|
8
|
-
:generate_caches,
|
9
|
-
:restore_caches,
|
2
|
+
|
3
|
+
each_delegate :cache,
|
4
|
+
:check,
|
5
|
+
:clear,
|
6
|
+
:backup,
|
7
|
+
:restore,
|
10
8
|
:to => :categories
|
11
|
-
|
9
|
+
|
12
10
|
end
|