picky 3.6.16 → 4.0.0pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. data/lib/picky/application.rb +1 -1
  2. data/lib/picky/backends/backend.rb +2 -0
  3. data/lib/picky/backends/memory.rb +14 -7
  4. data/lib/picky/backends/{memory → prepared}/text.rb +10 -4
  5. data/lib/picky/backends/redis/directly_manipulable.rb +3 -5
  6. data/lib/picky/backends/redis/list.rb +5 -1
  7. data/lib/picky/backends/sqlite/basic.rb +4 -2
  8. data/lib/picky/bundle.rb +6 -7
  9. data/lib/picky/bundle_indexed.rb +2 -2
  10. data/lib/picky/bundle_realtime.rb +8 -7
  11. data/lib/picky/categories.rb +0 -1
  12. data/lib/picky/categories_indexing.rb +14 -0
  13. data/lib/picky/category.rb +3 -5
  14. data/lib/picky/category_indexed.rb +2 -5
  15. data/lib/picky/category_indexing.rb +28 -16
  16. data/lib/picky/constants.rb +3 -1
  17. data/lib/picky/frontend_adapters/rack.rb +2 -2
  18. data/lib/picky/generators/similarity/phonetic.rb +6 -14
  19. data/lib/picky/generators/strategy.rb +1 -1
  20. data/lib/picky/generators/weights/runtime.rb +2 -2
  21. data/lib/picky/helpers/indexing.rb +20 -0
  22. data/lib/picky/index.rb +7 -10
  23. data/lib/picky/index_indexed.rb +1 -8
  24. data/lib/picky/index_indexing.rb +44 -42
  25. data/lib/picky/indexers/base.rb +5 -6
  26. data/lib/picky/indexers/parallel.rb +35 -32
  27. data/lib/picky/indexers/serial.rb +38 -15
  28. data/lib/picky/indexes_indexed.rb +0 -7
  29. data/lib/picky/indexes_indexing.rb +16 -19
  30. data/lib/picky/loader.rb +6 -4
  31. data/lib/picky/query/allocation.rb +7 -2
  32. data/lib/picky/query/combination.rb +1 -1
  33. data/lib/picky/query/indexes.rb +1 -1
  34. data/lib/picky/query/indexes_check.rb +12 -14
  35. data/lib/picky/query/token.rb +33 -15
  36. data/lib/picky/results/exact_first.rb +53 -0
  37. data/lib/picky/scheduler.rb +43 -0
  38. data/lib/picky/search.rb +0 -2
  39. data/lib/picky/sources/csv.rb +2 -3
  40. data/lib/picky/sources/db.rb +4 -3
  41. data/lib/picky/sources/mongo.rb +1 -1
  42. data/lib/picky/tokenizer.rb +0 -4
  43. data/lib/picky/wrappers/bundle/location.rb +1 -1
  44. data/lib/picky.rb +2 -2
  45. data/lib/tasks/index.rake +13 -14
  46. data/spec/functional/backends/file_spec.rb +2 -4
  47. data/spec/functional/backends/memory_spec.rb +2 -2
  48. data/spec/functional/backends/redis_spec.rb +1 -1
  49. data/spec/functional/exact_first_spec.rb +24 -4
  50. data/spec/functional/realtime_spec.rb +7 -3
  51. data/spec/lib/application_spec.rb +30 -30
  52. data/spec/lib/backends/backend_spec.rb +25 -27
  53. data/spec/lib/backends/{memory → prepared}/text_spec.rb +1 -1
  54. data/spec/lib/category_indexing_spec.rb +1 -1
  55. data/spec/lib/extensions/symbol_spec.rb +1 -1
  56. data/spec/lib/generators/similarity/phonetic_spec.rb +46 -0
  57. data/spec/lib/index_indexed_spec.rb +5 -5
  58. data/spec/lib/index_indexing_spec.rb +13 -12
  59. data/spec/lib/index_spec.rb +8 -8
  60. data/spec/lib/indexers/base_spec.rb +5 -6
  61. data/spec/lib/indexers/parallel_spec.rb +10 -10
  62. data/spec/lib/indexes_indexed_spec.rb +1 -7
  63. data/spec/lib/indexes_indexing_spec.rb +10 -5
  64. data/spec/lib/query/indexes_check_spec.rb +44 -15
  65. data/spec/lib/query/indexes_spec.rb +11 -11
  66. data/spec/lib/query/token_spec.rb +10 -0
  67. data/spec/lib/{indexed/wrappers → results}/exact_first_spec.rb +18 -21
  68. data/spec/lib/scheduler_spec.rb +92 -0
  69. metadata +45 -34
  70. data/lib/picky/cores.rb +0 -127
  71. data/lib/picky/tokenizers/location.rb +0 -53
  72. data/lib/picky/wrappers/category/exact_first.rb +0 -94
  73. data/spec/lib/cores_spec.rb +0 -185
@@ -4,30 +4,14 @@ module Picky
4
4
  #
5
5
  class Index
6
6
 
7
+ include Helpers::Indexing
8
+
7
9
  # Delegators for indexing.
8
10
  #
9
11
  delegate :cache,
10
12
  :clear,
11
- :prepare,
12
13
  :to => :categories
13
14
 
14
- # Calling index on an index will call index
15
- # on every category.
16
- #
17
- # Decides whether to use a parallel indexer or whether to
18
- # delegate to each category to index themselves.
19
- #
20
- def index
21
- if source.respond_to?(:each)
22
- check_source_empty
23
- index_in_parallel
24
- else
25
- with_data_snapshot do
26
- categories.index
27
- end
28
- end
29
- end
30
-
31
15
  # Define an index tokenizer on the index.
32
16
  #
33
17
  # Parameters are the exact same as for indexing.
@@ -39,7 +23,35 @@ module Picky
39
23
  options && Tokenizer.new(options)
40
24
  end
41
25
  end
42
- alias define_indexing indexing
26
+
27
+ #
28
+ #
29
+ def index scheduler = Scheduler.new
30
+ timed_indexing scheduler do
31
+ prepare scheduler
32
+ scheduler.finish
33
+
34
+ cache scheduler
35
+ scheduler.finish
36
+ end
37
+ end
38
+
39
+ # Calling prepare on an index will call prepare
40
+ # on every category.
41
+ #
42
+ # Decides whether to use a parallel indexer or whether to
43
+ # delegate to each category to prepare themselves.
44
+ #
45
+ def prepare scheduler = Scheduler.new
46
+ if source.respond_to?(:each)
47
+ check_source_empty
48
+ prepare_in_parallel scheduler
49
+ else
50
+ with_data_snapshot do
51
+ categories.prepare scheduler
52
+ end
53
+ end
54
+ end
43
55
 
44
56
  # Check if the given enumerable source is empty.
45
57
  #
@@ -50,6 +62,15 @@ module Picky
50
62
  warn %Q{\n\033[1mWarning\033[m, source for index "#{name}" is empty: #{source} (responds true to empty?).\n} if source.respond_to?(:empty?) && source.empty?
51
63
  end
52
64
 
65
+ # Indexes the categories in parallel.
66
+ #
67
+ # Only use where the category does have a #each source defined.
68
+ #
69
+ def prepare_in_parallel scheduler
70
+ indexer = Indexers::Parallel.new self
71
+ indexer.prepare categories, scheduler
72
+ end
73
+
53
74
  # Note: Duplicated in category_indexing.rb.
54
75
  #
55
76
  # Take a data snapshot if the source offers it.
@@ -64,15 +85,6 @@ module Picky
64
85
  end
65
86
  end
66
87
 
67
- # Indexes the categories in parallel.
68
- #
69
- # Only use where the category does have a #each source defined.
70
- #
71
- def index_in_parallel
72
- indexer = Indexers::Parallel.new self
73
- indexer.index categories
74
- end
75
-
76
88
  # Returns the installed tokenizer or the default.
77
89
  #
78
90
  def tokenizer
@@ -87,7 +99,7 @@ module Picky
87
99
  #
88
100
  def source some_source = nil, &block
89
101
  some_source ||= block
90
- some_source ? define_source(some_source) : (@source && extract_source)
102
+ some_source ? (check_source(some_source); @source = some_source) : (@source && extract_source)
91
103
  end
92
104
  # Extract the actual source if it is wrapped in a time
93
105
  # capsule, i.e. a block/lambda.
@@ -97,10 +109,6 @@ module Picky
97
109
  def extract_source
98
110
  @source = @source.respond_to?(:call) ? @source.call : @source
99
111
  end
100
- def define_source source
101
- check_source source
102
- @source = source
103
- end
104
112
  def check_source source # :nodoc:
105
113
  raise ArgumentError.new(<<-SOURCE
106
114
 
@@ -119,21 +127,15 @@ SOURCE
119
127
  #
120
128
  # Parameter is a method name to use on the key (e.g. :to_i, :to_s, :strip).
121
129
  #
122
- def key_format format = nil
123
- format ? define_key_format(format) : @key_format
124
- end
125
- def define_key_format key_format
126
- @key_format = key_format
130
+ def key_format key_format = nil
131
+ key_format ? (@key_format = key_format) : @key_format
127
132
  end
128
133
 
129
134
  # Define what to do after indexing.
130
135
  # (Only used in the Sources::DB)
131
136
  #
132
137
  def after_indexing after_indexing = nil
133
- after_indexing ? define_after_indexing(after_indexing) : @after_indexing
134
- end
135
- def define_after_indexing after_indexing
136
- @after_indexing = after_indexing
138
+ after_indexing ? (@after_indexing = after_indexing) : @after_indexing
137
139
  end
138
140
 
139
141
  end
@@ -19,21 +19,20 @@ module Picky
19
19
 
20
20
  # Starts the indexing process.
21
21
  #
22
- def index categories
22
+ def prepare categories, scheduler = Scheduler.new
23
23
  check_source
24
24
  categories.empty
25
- process categories do |file|
26
- notify_finished file
25
+ process categories, scheduler do |prepared_file|
26
+ notify_finished prepared_file
27
27
  end
28
- categories.cache
29
28
  end
30
29
 
31
30
  def check_source # :nodoc:
32
31
  raise "Trying to index without a source for #{@index_or_category.name}." unless source
33
32
  end
34
33
 
35
- def notify_finished file
36
- timed_exclaim %Q{"#{@index_or_category.identifier}": Tokenized -> #{file.path.gsub("#{PICKY_ROOT}/", '')}.}
34
+ def notify_finished prepared_file
35
+ timed_exclaim %Q{ "#{@index_or_category.identifier}": Tokenized -> #{prepared_file.path.gsub("#{PICKY_ROOT}/", '')}.}
37
36
  end
38
37
 
39
38
  end
@@ -15,62 +15,65 @@ module Picky
15
15
  # Parameters:
16
16
  # * categories: An Enumerable of Category-s.
17
17
  #
18
- def process categories
19
- comma = ?,
20
- newline = ?\n
21
-
18
+ def process categories, scheduler = Scheduler.new
22
19
  # Prepare a combined object - array.
23
20
  #
24
21
  combined = categories.map do |category|
25
- [category, [], category.prepared_index_file, (category.tokenizer || tokenizer)]
22
+ [category, category.prepared_index_file, [], (category.tokenizer || tokenizer)]
26
23
  end
27
24
 
28
- # Index.
29
- #
30
- # TODO Extract into flush_every(100_000) do
31
- #
32
- i = 0
33
-
34
25
  # Explicitly reset the source to avoid caching trouble.
35
26
  #
36
27
  source.reset if source.respond_to?(:reset)
37
28
 
38
29
  # Go through each object in the source.
39
30
  #
31
+ objects = []
32
+
40
33
  source.each do |object|
41
- id = object.id
42
34
 
43
- # This needs to be rewritten.
35
+ # Accumulate objects.
44
36
  #
45
- # Is it a good idea that not the tokenizer has control over when he gets the next text?
37
+ objects << object
38
+ next if objects.size < 10_000
39
+
40
+ # THINK Is it a good idea that not the tokenizer has
41
+ # control over when he gets the next text?
46
42
  #
47
- combined.each do |category, cache, _, tokenizer|
48
- tokens, _ = tokenizer.tokenize object.send(category.from) # Note: Originals not needed.
49
- tokens.each do |token_text|
50
- next unless token_text
51
- cache << id << comma << token_text << newline
52
- end
43
+ combined.each do |category, file, cache, tokenizer|
44
+ index_flush objects, file, category, cache, tokenizer
53
45
  end
54
46
 
55
- if i >= 100_000
56
- flush combined
57
- i = 0
58
- end
59
- i += 1
47
+ objects.clear
48
+
60
49
  end
61
- flush combined
62
- combined.each do |_, _, file, _|
50
+
51
+ # Close all files.
52
+ #
53
+ combined.each do |category, file, cache, tokenizer|
54
+ index_flush objects, file, category, cache, tokenizer
63
55
  yield file
64
56
  file.close
65
57
  end
66
58
  end
67
59
 
68
- # Flush the combined array into the file.
69
- #
70
- def flush combined # :nodoc:
71
- combined.each do |_, cache, file, _|
72
- file.write(cache.join) && cache.clear
60
+ def index_flush objects, file, category, cache, tokenizer
61
+ comma = ?,
62
+ newline = ?\n
63
+
64
+ objects.each do |object|
65
+ tokens, _ = tokenizer.tokenize object.send(category.from) # Note: Originals not needed.
66
+ tokens.each do |token_text|
67
+ next unless token_text
68
+ cache << object.id << comma << token_text << newline
69
+ end
73
70
  end
71
+
72
+ flush file, cache
73
+ end
74
+
75
+ def flush file, cache
76
+ file.write(cache.join) && cache.clear
74
77
  end
75
78
 
76
79
  end
@@ -16,33 +16,56 @@ module Picky
16
16
  # Parameters:
17
17
  # * categories: An enumerable of Category-s.
18
18
  #
19
- def process categories
20
- comma = ?,
21
- newline = ?\n
22
-
19
+ def process categories, scheduler = Scheduler.new
23
20
  categories.each do |category|
24
21
 
25
- tokenizer = category.tokenizer
26
-
27
22
  category.prepared_index_file do |file|
23
+
24
+ datas = []
28
25
  result = []
26
+ tokenizer = category.tokenizer
27
+
28
+ source.harvest(category) do |*data|
29
+
30
+ # Accumulate data.
31
+ #
32
+ datas << data
33
+ next if datas.size < 10_000
34
+
35
+ # Opening the file inside the scheduler to
36
+ # have it automagically closed.
37
+ #
38
+ index_flush datas, file, result, tokenizer
39
+
40
+ datas.clear
29
41
 
30
- source.harvest(category) do |indexed_id, text|
31
- tokens, _ = tokenizer.tokenize text # Note: Originals not needed.
32
- tokens.each do |token_text|
33
- next unless token_text
34
- result << indexed_id << comma << token_text << newline
35
- end
36
- file.write(result.join) && result.clear if result.size > 100_000
37
42
  end
38
43
 
39
- yield file
44
+ index_flush datas, file, result, tokenizer
40
45
 
41
- file.write result.join
46
+ yield file
42
47
  end
48
+ end
49
+
50
+ end
51
+
52
+ def index_flush datas, file, cache, tokenizer
53
+ comma = ?,
54
+ newline = ?\n
43
55
 
56
+ datas.each do |indexed_id, text|
57
+ tokens, _ = tokenizer.tokenize text # Note: Originals not needed.
58
+ tokens.each do |token_text|
59
+ next unless token_text
60
+ cache << indexed_id << comma << token_text << newline
61
+ end
44
62
  end
45
63
 
64
+ flush file, cache
65
+ end
66
+
67
+ def flush prepared_file, cache
68
+ prepared_file.write(cache.join) && cache.clear
46
69
  end
47
70
 
48
71
  end
@@ -8,15 +8,8 @@ module Picky
8
8
  :analyze
9
9
 
10
10
  each_delegate :load,
11
- :reload,
12
11
  :to => :indexes
13
12
 
14
- # TODO Remove in 4.0.
15
- #
16
- def self.reload
17
- self.instance.reload
18
- end
19
-
20
13
  end
21
14
 
22
15
  end
@@ -4,35 +4,32 @@ module Picky
4
4
  #
5
5
  class Indexes
6
6
 
7
- instance_delegate :index,
8
- :clear,
9
- :index_for_tests,
7
+ extend Helpers::Indexing
8
+
9
+ instance_delegate :clear,
10
10
  :tokenizer
11
11
 
12
12
  each_delegate :clear,
13
13
  :to => :indexes
14
14
 
15
- # Runs the indexers in parallel (prepare + cache).
16
15
  #
17
- def index randomly = true
18
- # Run in parallel.
19
- #
20
- timed_exclaim "Indexing using #{Cores.max_processors} processors, in #{randomly ? 'random' : 'given'} order."
21
-
22
- # Run indexing/caching forked.
23
- #
24
- Cores.forked self.indexes, { randomly: randomly }, &:index
25
-
26
- timed_exclaim "Indexing finished."
16
+ #
17
+ def self.index scheduler = Scheduler.new
18
+ timed_indexing scheduler do
19
+ instance.index scheduler
20
+ end
27
21
  end
28
22
 
29
- # For integration testing – indexes for the tests
30
- # without forking and shouting ;)
31
23
  #
32
- # TODO Rename to #index_without_forking, or just #index.
33
24
  #
34
- def index_for_tests
35
- indexes.each(&:index)
25
+ def index scheduler = Scheduler.new
26
+ indexes.each { |index| index.prepare scheduler }
27
+ scheduler.finish
28
+
29
+ timed_exclaim "Tokenizing finished, generating data for indexes from tokenized data."
30
+
31
+ indexes.each { |index| index.cache scheduler }
32
+ scheduler.finish
36
33
  end
37
34
 
38
35
  #
data/lib/picky/loader.rb CHANGED
@@ -64,6 +64,7 @@ module Picky
64
64
  # Requiring Helpers
65
65
  #
66
66
  load_relative 'helpers/measuring'
67
+ load_relative 'helpers/indexing'
67
68
 
68
69
  # Calculations.
69
70
  #
@@ -112,9 +113,10 @@ module Picky
112
113
  load_relative 'backends/helpers/file'
113
114
  load_relative 'backends/backend'
114
115
 
116
+ load_relative 'backends/prepared/text'
117
+
115
118
  load_relative 'backends/memory'
116
119
  load_relative 'backends/memory/basic'
117
- load_relative 'backends/memory/text'
118
120
  load_relative 'backends/memory/marshal'
119
121
  load_relative 'backends/memory/json'
120
122
 
@@ -147,7 +149,6 @@ module Picky
147
149
  # Wrappers.
148
150
  #
149
151
  load_relative 'wrappers/category/location'
150
- load_relative 'wrappers/category/exact_first'
151
152
 
152
153
  load_relative 'wrappers/bundle/delegators'
153
154
  load_relative 'wrappers/bundle/wrapper'
@@ -237,6 +238,7 @@ module Picky
237
238
  # Results.
238
239
  #
239
240
  load_relative 'results'
241
+ load_relative 'results/exact_first'
240
242
 
241
243
  # Search.
242
244
  #
@@ -259,9 +261,9 @@ module Picky
259
261
  #
260
262
  load_relative 'application'
261
263
 
262
- # Load tools. Load in specific case?
264
+ # Load tools. Load specifically?
263
265
  #
264
- load_relative 'cores'
266
+ load_relative 'scheduler'
265
267
 
266
268
  # Load migration notices.
267
269
  #
@@ -16,8 +16,11 @@ module Picky
16
16
  #
17
17
  def initialize index, combinations
18
18
  @combinations = combinations
19
- @result_identifier = index.result_identifier # TODO Make cleverer.
20
- @backend = index.backend # TODO Make cleverer. Use inverted?
19
+
20
+ # Could this be rewritten?
21
+ #
22
+ @result_identifier = index.result_identifier
23
+ @backend = index.backend
21
24
  end
22
25
 
23
26
  def hash
@@ -49,6 +52,8 @@ module Picky
49
52
 
50
53
  # This starts the searching process.
51
54
  #
55
+ # Returns the calculated ids (from the offset).
56
+ #
52
57
  def process! amount, offset
53
58
  ids = calculate_ids amount, offset
54
59
  @count = ids.size # cache the count before throwing away the ids
@@ -51,7 +51,7 @@ module Picky
51
51
 
52
52
  # Note: Required for uniq!
53
53
  #
54
- # TODO Ok with category or is the bundle needed?
54
+ # THINK Ok with category or is the bundle needed?
55
55
  #
56
56
  def hash
57
57
  [token, category].hash
@@ -22,7 +22,7 @@ module Picky
22
22
  # Note: We cannot mix memory and redis indexes just yet.
23
23
  #
24
24
  def initialize *indexes
25
- IndexesCheck.check_backend_types indexes
25
+ IndexesCheck.check_backends indexes
26
26
 
27
27
  @indexes = indexes
28
28
 
@@ -2,8 +2,6 @@ module Picky
2
2
 
3
3
  module Query
4
4
 
5
- # TODO Remove.
6
- #
7
5
  class IndexesCheck
8
6
 
9
7
  class << self
@@ -14,16 +12,16 @@ module Picky
14
12
  # Currently it isn't possible using Memory and Redis etc.
15
13
  # indexes in the same query index group.
16
14
  #
17
- # Picky will raise a Query::Indexes::DifferentTypesError.
15
+ # Picky will raise a Query::Indexes::DifferentBackendsError.
18
16
  #
19
- def check_backend_types index_definitions_ary # :nodoc:
20
- backend_types = index_definitions_ary.map(&:backend).map(&:class)
21
- backend_types.uniq!
22
- raise_different backend_types if backend_types.size > 1
23
- backend_types
17
+ def check_backends indexes # :nodoc:
18
+ backends = indexes.map &:backend
19
+ backends.uniq! &:class
20
+ raise_different backends if backends.size > 1
21
+ backends
24
22
  end
25
- def raise_different backend_types # :nodoc:
26
- raise DifferentTypesError.new(backend_types)
23
+ def raise_different backends # :nodoc:
24
+ raise DifferentBackendsError.new(backends)
27
25
  end
28
26
 
29
27
  end
@@ -33,12 +31,12 @@ module Picky
33
31
  # Currently it isn't possible using Memory and Redis etc.
34
32
  # indexes in the same query index group.
35
33
  #
36
- class DifferentTypesError < StandardError # :nodoc:all
37
- def initialize types
38
- @types = types
34
+ class DifferentBackendsError < StandardError # :nodoc:all
35
+ def initialize backends
36
+ @backends = backends
39
37
  end
40
38
  def to_s
41
- "Currently it isn't possible to mix Indexes with backends #{@types.join(" and ")} in the same Search instance."
39
+ "Currently it isn't possible to mix Indexes with backends #{@backends.join(" and ")} in the same Search instance."
42
40
  end
43
41
  end
44
42
 
@@ -6,7 +6,8 @@ module Picky
6
6
  #
7
7
  # It remembers the original form, and and a normalized form.
8
8
  #
9
- # It also knows whether it needs to look for similarity (bla~), or whether it is a partial (bla*).
9
+ # It also knows whether it needs to look for similarity (bla~),
10
+ # or whether it is a partial (bla*).
10
11
  #
11
12
  class Token # :nodoc:all
12
13
 
@@ -17,7 +18,8 @@ module Picky
17
18
 
18
19
  # Normal initializer.
19
20
  #
20
- # Note: Use this if you do not want a normalized token.
21
+ # Note:
22
+ # Use this if you do not want a normalized token.
21
23
  #
22
24
  def initialize text, original = nil
23
25
  @text = text
@@ -26,21 +28,25 @@ module Picky
26
28
 
27
29
  # Returns a qualified and normalized token.
28
30
  #
29
- # Note: Use this in the search engine if you need a qualified
30
- # and normalized token. I.e. one prepared for a search.
31
+ # Note:
32
+ # Use this in the search engine if you need a qualified
33
+ # and normalized token. I.e. one prepared for a search.
31
34
  #
32
35
  def self.processed text, original = nil
33
36
  new(text, original).process
34
37
  end
35
- def process # TODO Move this into the processed method and let the token have more params?
36
- qualify # TODO Should this operate on the original?
37
- partialize # TODO Should this operate on the original?
38
- similarize # TODO Should this operate on the original?
39
- remove_illegals # TODO Remove?
38
+ def process
39
+ qualify
40
+ partialize
41
+ similarize
42
+ remove_illegals
40
43
  self
41
44
  end
42
45
 
46
+ # Symbolizes this token's text.
43
47
  #
48
+ # Note:
49
+ # Call externally when Picky operates in Symbols mode.
44
50
  #
45
51
  def symbolize!
46
52
  @text = @text.to_sym
@@ -48,7 +54,10 @@ module Picky
48
54
 
49
55
  # Translates this token's qualifiers into actual categories.
50
56
  #
51
- # Note: If this is not done, there is no mapping.
57
+ # Note:
58
+ # If this is not done, there is no mapping.
59
+ #
60
+ # THINK Can this be improved somehow?
52
61
  #
53
62
  def categorize mapper
54
63
  @user_defined_categories = @qualifiers && @qualifiers.map do |qualifier|
@@ -63,13 +72,22 @@ module Picky
63
72
  def partial= partial
64
73
  @partial = partial if @partial.nil?
65
74
  end
75
+
76
+ # A token is partial? only if it not similar
77
+ # and is partial.
78
+ #
79
+ # It can't be similar and partial at the same time.
80
+ #
66
81
  def partial?
67
82
  !@similar && @partial
68
83
  end
69
84
 
70
- # If the text ends with *, partialize it. If with ", don't.
85
+ # If the text ends with *, partialize it. If with ",
86
+ # non-partialize it.
71
87
  #
72
- # The latter wins. So "hello*" will not be partially searched.
88
+ # The last one wins.
89
+ # So "hello*" will not be partially searched.
90
+ # So "hello"* will be partially searched.
73
91
  #
74
92
  @@no_partial = /\"\Z/
75
93
  @@partial = /\*\Z/
@@ -97,7 +115,7 @@ module Picky
97
115
  #
98
116
  @@illegals = /["*~]/
99
117
  def remove_illegals
100
- @text.gsub! @@illegals, '' unless @text.blank?
118
+ @text.gsub! @@illegals, EMPTY_STRING unless @text.blank?
101
119
  end
102
120
 
103
121
  # Returns an array of possible combinations.
@@ -140,9 +158,9 @@ module Picky
140
158
  @@split_qualifier_text = ':'
141
159
  @@split_qualifiers = ','
142
160
  def qualify
143
- @qualifiers, @text = (@text || '').split(@@split_qualifier_text, 2)
161
+ @qualifiers, @text = (@text || EMPTY_STRING).split(@@split_qualifier_text, 2)
144
162
  @qualifiers, @text = if @text.blank?
145
- [nil, (@qualifiers || '')]
163
+ [nil, (@qualifiers || EMPTY_STRING)]
146
164
  else
147
165
  [@qualifiers.split(@@split_qualifiers), @text]
148
166
  end