picky 3.5.4 → 3.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/lib/picky/backends/backend.rb +1 -1
  2. data/lib/picky/backends/file/basic.rb +0 -36
  3. data/lib/picky/backends/file/json.rb +1 -1
  4. data/lib/picky/backends/file.rb +4 -4
  5. data/lib/picky/backends/helpers/file.rb +0 -26
  6. data/lib/picky/backends/memory/basic.rb +0 -35
  7. data/lib/picky/backends/memory.rb +4 -4
  8. data/lib/picky/backends/redis/basic.rb +0 -33
  9. data/lib/picky/backends/redis.rb +4 -4
  10. data/lib/picky/backends/sqlite/db.rb +84 -0
  11. data/lib/picky/backends/sqlite.rb +75 -0
  12. data/lib/picky/bundle.rb +15 -87
  13. data/lib/picky/bundle_realtime.rb +1 -1
  14. data/lib/picky/categories.rb +1 -0
  15. data/lib/picky/categories_indexed.rb +1 -1
  16. data/lib/picky/categories_indexing.rb +1 -3
  17. data/lib/picky/category.rb +16 -2
  18. data/lib/picky/category_indexed.rb +5 -3
  19. data/lib/picky/category_indexing.rb +0 -26
  20. data/lib/picky/category_realtime.rb +2 -0
  21. data/lib/picky/extensions/string.rb +20 -0
  22. data/lib/picky/extensions/symbol.rb +22 -0
  23. data/lib/picky/generators/similarity/double_metaphone.rb +1 -2
  24. data/lib/picky/generators/similarity/metaphone.rb +1 -2
  25. data/lib/picky/generators/similarity/phonetic.rb +0 -10
  26. data/lib/picky/generators/similarity/soundex.rb +1 -2
  27. data/lib/picky/index.rb +9 -2
  28. data/lib/picky/index_indexed.rb +4 -4
  29. data/lib/picky/index_indexing.rb +1 -5
  30. data/lib/picky/indexes_indexed.rb +7 -6
  31. data/lib/picky/indexes_indexing.rb +1 -7
  32. data/lib/picky/loader.rb +4 -1
  33. data/lib/picky/sources/couch.rb +1 -1
  34. data/lib/picky/sources/mongo.rb +1 -1
  35. data/lib/picky/wrappers/bundle/calculation.rb +1 -1
  36. data/lib/picky/wrappers/bundle/exact_partial.rb +3 -12
  37. data/lib/picky/wrappers/bundle/location.rb +1 -0
  38. data/lib/tasks/index.rake +0 -4
  39. data/spec/lib/backends/file/basic_spec.rb +5 -17
  40. data/spec/lib/backends/memory/basic_spec.rb +5 -17
  41. data/spec/lib/backends/redis/basic_spec.rb +5 -52
  42. data/spec/lib/backends/sqlite/db_spec.rb +80 -0
  43. data/spec/lib/backends/sqlite_spec.rb +131 -0
  44. data/spec/lib/category_indexed_spec.rb +2 -2
  45. data/spec/lib/category_indexing_spec.rb +0 -24
  46. data/spec/lib/extensions/string_spec.rb +16 -0
  47. data/spec/lib/extensions/symbol_spec.rb +16 -0
  48. data/spec/lib/index_indexed_spec.rb +16 -16
  49. data/spec/lib/indexes_indexed_spec.rb +13 -7
  50. data/spec/lib/indexes_indexing_spec.rb +3 -6
  51. data/spec/lib/indexing/bundle_spec.rb +6 -125
  52. data/spec/lib/sources/couch_spec.rb +8 -8
  53. data/spec/lib/sources/mongo_spec.rb +5 -5
  54. data/spec/specific/realtime_spec.rb +397 -173
  55. metadata +44 -29
  56. data/lib/picky/bundling.rb +0 -10
  57. data/lib/tasks/checks.rake +0 -13
@@ -6,13 +6,15 @@ module Picky
6
6
 
7
7
  # Loads the index from cache.
8
8
  #
9
- def load_from_cache
9
+ def load
10
10
  timed_exclaim %Q{"#{identifier}": Loading index from cache.}
11
- clear_realtime_mapping
11
+ clear_realtime_mapping # TODO What to do?
12
12
  exact.load
13
13
  partial.load
14
14
  end
15
- alias reload load_from_cache
15
+ # TODO Remove in 4.0.
16
+ #
17
+ alias reload load
16
18
 
17
19
  # Gets the weight for this token's text.
18
20
  #
@@ -107,14 +107,6 @@ module Picky
107
107
  @tokenizer || @index.tokenizer
108
108
  end
109
109
 
110
- # Checks the caches for existence.
111
- #
112
- def check
113
- timed_exclaim "Checking #{identifier}."
114
- exact.raise_unless_cache_exists
115
- partial.raise_unless_cache_exists
116
- end
117
-
118
110
  # Deletes the caches.
119
111
  #
120
112
  def clear
@@ -123,24 +115,6 @@ module Picky
123
115
  partial.delete
124
116
  end
125
117
 
126
- # Backup the caches.
127
- # (Revert with restore_caches)
128
- #
129
- def backup
130
- timed_exclaim "Backing up #{identifier}."
131
- exact.backup
132
- partial.backup
133
- end
134
-
135
- # Restore the caches.
136
- # (Revert with backup_caches)
137
- #
138
- def restore
139
- timed_exclaim "Restoring #{identifier}."
140
- exact.restore
141
- partial.restore
142
- end
143
-
144
118
  end
145
119
 
146
120
  end
@@ -6,6 +6,7 @@ module Picky
6
6
  # given id.
7
7
  #
8
8
  def remove id
9
+ id = id.send key_format
9
10
  exact.remove id
10
11
  partial.remove id
11
12
  end
@@ -38,6 +39,7 @@ module Picky
38
39
  def add_tokenized_token id, text, where = :unshift
39
40
  return unless text
40
41
  id = id.send key_format # TODO Speed this up!
42
+
41
43
  # text = text.to_sym if @symbols # TODO Symbols.
42
44
  exact.add id, text, where
43
45
  partial.add_partialized id, text, where
@@ -2,6 +2,26 @@
2
2
  #
3
3
  class String # :nodoc:all
4
4
 
5
+ # Returns a _single_ double metaphone code
6
+ # for this string.
7
+ #
8
+ def double_metaphone
9
+ codes = Text::Metaphone.double_metaphone self
10
+ codes.first unless codes.empty?
11
+ end
12
+
13
+ # Returns a metaphone code for this string.
14
+ #
15
+ def metaphone
16
+ Text::Metaphone.metaphone self
17
+ end
18
+
19
+ # Returns a soundex code for this string.
20
+ #
21
+ def soundex
22
+ Text::Soundex.soundex self
23
+ end
24
+
5
25
  # 'keys'.each_subtoken # => yields each of ['keys', 'key', 'ke', 'k']
6
26
  # 'keys'.each_subtoken(2) # => yields each of ['keys', 'key', 'ke']
7
27
  #
@@ -2,6 +2,28 @@
2
2
  #
3
3
  class Symbol # :nodoc:all
4
4
 
5
+ # Returns a _single_ double metaphone code
6
+ # for this symbol.
7
+ #
8
+ def double_metaphone
9
+ codes = Text::Metaphone.double_metaphone self
10
+ codes.first.intern unless codes.empty?
11
+ end
12
+
13
+ # Returns a metaphone code for this symbol.
14
+ #
15
+ def metaphone
16
+ code = Text::Metaphone.metaphone self.to_s
17
+ code.intern if code
18
+ end
19
+
20
+ # Returns a soundex code for this symbol.
21
+ #
22
+ def soundex
23
+ code = Text::Soundex.soundex self.to_s
24
+ code.intern if code
25
+ end
26
+
5
27
  # :keys.each_subtoken # => yields each of [:keys, :key, :ke, :k]
6
28
  # :keys.each_subtoken(2) # => yields each of [:keys, :key, :ke]
7
29
  #
@@ -19,8 +19,7 @@ module Picky
19
19
  # Returns a symbol.
20
20
  #
21
21
  def encoded str_or_sym
22
- codes = Text::Metaphone.double_metaphone str_or_sym.to_s
23
- codes.first.intern unless codes.empty?
22
+ str_or_sym.double_metaphone
24
23
  end
25
24
 
26
25
  end
@@ -19,8 +19,7 @@ module Picky
19
19
  # Returns a symbol.
20
20
  #
21
21
  def encoded str_or_sym
22
- code = Text::Metaphone.metaphone str_or_sym.to_s
23
- code.intern if code
22
+ str_or_sym.metaphone
24
23
  end
25
24
 
26
25
  end
@@ -23,16 +23,6 @@ module Picky
23
23
  @amount = amount
24
24
  end
25
25
 
26
- # # Generates an index for the given index (in exact index style).
27
- # #
28
- # # In the following form:
29
- # # [:meier, :mueller, :peter, :pater] => { MR: [:meier], MLR: [:mueller], PTR: [:peter, :pater] }
30
- # #
31
- # def generate_from inverted
32
- # hash = hashify inverted.keys
33
- # sort hash
34
- # end
35
-
36
26
  protected
37
27
 
38
28
  # Sorts the index values in place.
@@ -19,8 +19,7 @@ module Picky
19
19
  # Returns a symbol.
20
20
  #
21
21
  def encoded str_or_sym
22
- code = Text::Soundex.soundex str_or_sym.to_s
23
- code.intern if code
22
+ str_or_sym.soundex
24
23
  end
25
24
 
26
25
  end
data/lib/picky/index.rb CHANGED
@@ -132,11 +132,18 @@ module Picky
132
132
  #
133
133
  def backend backend = nil
134
134
  if backend
135
- @backend = backend
135
+ @backend = reset_backend backend
136
136
  else
137
- @backend || Backends::Memory.new
137
+ @backend ||= Backends::Memory.new
138
138
  end
139
139
  end
140
+ # TODO Rewrite such that reset_backend just sets the
141
+ # lazily evaluated backend to nil.
142
+ #
143
+ def reset_backend backend
144
+ categories.reset_backend backend
145
+ backend
146
+ end
140
147
 
141
148
  # TODO Symbols.
142
149
  #
@@ -4,15 +4,15 @@ module Picky
4
4
  #
5
5
  class Index
6
6
 
7
- attr_reader :combinator
8
-
9
- delegate :load_from_cache,
7
+ delegate :load,
10
8
  :analyze,
11
9
  :reindex,
12
10
  :possible_combinations,
13
11
  :to => :categories
14
12
 
15
- alias reload load_from_cache
13
+ # TODO Remove in 4.0.
14
+ #
15
+ alias reload load
16
16
 
17
17
  # Define how the results of this index are identified.
18
18
  # (Shown in the client, for example)
@@ -4,15 +4,11 @@ module Picky
4
4
  #
5
5
  class Index
6
6
 
7
- attr_reader :bundle_class
8
-
9
7
  # Delegators for indexing.
10
8
  #
11
9
  delegate :cache,
12
- :check,
13
10
  :clear,
14
- :backup,
15
- :restore,
11
+ :prepare,
16
12
  :to => :categories
17
13
 
18
14
  # Calling index on an index will call index
@@ -4,17 +4,18 @@ module Picky
4
4
  #
5
5
  class Indexes
6
6
 
7
- instance_delegate :load_from_cache,
8
- :reload,
7
+ instance_delegate :load,
9
8
  :analyze
10
9
 
11
- each_delegate :load_from_cache,
10
+ each_delegate :load,
11
+ :reload,
12
12
  :to => :indexes
13
13
 
14
- # Reloads all indexes, one after another,
15
- # in the order they were added.
14
+ # TODO Remove in 4.0.
16
15
  #
17
- alias reload load_from_cache
16
+ def self.reload
17
+ self.instance.reload
18
+ end
18
19
 
19
20
  end
20
21
 
@@ -5,17 +5,11 @@ module Picky
5
5
  class Indexes
6
6
 
7
7
  instance_delegate :index,
8
- :check,
9
8
  :clear,
10
- :backup,
11
- :restore,
12
9
  :index_for_tests,
13
10
  :tokenizer
14
11
 
15
- each_delegate :check,
16
- :clear,
17
- :backup,
18
- :restore,
12
+ each_delegate :clear,
19
13
  :to => :indexes
20
14
 
21
15
  # Runs the indexers in parallel (prepare + cache).
data/lib/picky/loader.rb CHANGED
@@ -128,6 +128,9 @@ module Picky
128
128
  load_relative 'backends/file/basic'
129
129
  load_relative 'backends/file/json'
130
130
 
131
+ load_relative 'backends/sqlite'
132
+ load_relative 'backends/sqlite/db'
133
+
131
134
  # Indexing and Indexed things.
132
135
  #
133
136
  load_relative 'bundle'
@@ -264,4 +267,4 @@ module Picky
264
267
 
265
268
  end
266
269
 
267
- end
270
+ end
@@ -32,7 +32,7 @@ module Picky
32
32
  @db = RestClient::Resource.new options.delete(:url), options
33
33
 
34
34
  key_format = options.delete :key_format
35
- @key_format = key_format && key_format.intern || :to_sym
35
+ @key_format = key_format && key_format.intern || :to_s
36
36
  end
37
37
 
38
38
  def to_s
@@ -37,7 +37,7 @@ module Picky
37
37
 
38
38
  @db = RestClient::Resource.new options.delete(:url), options
39
39
  @database = options.delete(:db)
40
- @key_format = options[:key_format] && options[:key_format].intern || :to_sym
40
+ @key_format = options[:key_format] && options[:key_format].intern || :to_s
41
41
  end
42
42
 
43
43
  # Tries to require the rest_client gem.
@@ -24,7 +24,7 @@ module Picky
24
24
  float
25
25
  end
26
26
 
27
- # TODO Symbols.
27
+ # TODO Symbols. Use a block here?
28
28
  #
29
29
  def ids float_str
30
30
  @bundle.ids calculate(float_str.to_f).to_s
@@ -10,22 +10,13 @@ module Picky
10
10
  # bundle such that a partial index will not
11
11
  # be dumped or generated.
12
12
  #
13
- class ExactPartial
14
-
15
- attr_reader :bundle
16
-
17
- include Delegator
18
- include IndexedDelegator
19
-
20
- def initialize bundle
21
- @bundle = bundle
22
- end
13
+ class ExactPartial < Wrapper
23
14
 
15
+ # Ignore these.
16
+ #
24
17
  def clear; end
25
18
  def dump; end
26
19
  def empty; end
27
- def generate_caches_from_memory; end
28
- def generate_partial_from arg; end
29
20
  def index; end
30
21
  def load; end
31
22
 
@@ -52,6 +52,7 @@ module Picky
52
52
  bundle.load
53
53
 
54
54
  # TODO Symbols (of the location_anchor!!!).
55
+ # It should always be a Symbol.
55
56
  #
56
57
  @calculation.anchor = bundle['location_anchor'] && bundle['location_anchor'].to_f || raise("Configuration 'location_anchor' for #{bundle.identifier} missing. Did you run rake index already?")
57
58
  end
data/lib/tasks/index.rake CHANGED
@@ -12,13 +12,9 @@ end
12
12
 
13
13
  namespace :index do
14
14
 
15
- # Advanced usage.
16
- #
17
- # desc "Takes a snapshot, indexes, and caches in random order."
18
15
  task :randomly => :application do
19
16
  Picky::Indexes.index true
20
17
  end
21
- # desc "Takes a snapshot, indexes, and caches in order given."
22
18
  task :ordered => :application do
23
19
  Picky::Indexes.index false
24
20
  end
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Picky::Backends::File::Basic do
4
-
4
+
5
5
  context 'without options' do
6
6
  let(:basic) { described_class.new 'some/cache/path/to/file' }
7
7
 
@@ -10,32 +10,20 @@ describe Picky::Backends::File::Basic do
10
10
  basic.empty.should == {}
11
11
  end
12
12
  end
13
-
13
+
14
14
  describe 'initial' do
15
15
  it 'returns the container that is used for indexing' do
16
16
  basic.initial.should == nil
17
17
  end
18
18
  end
19
19
 
20
- describe 'backup_file_path_of' do
21
- it 'returns a backup path relative to the path' do
22
- basic.backup_file_path_of('some/path/to/some.memory.index').should == 'some/path/to/backup/some.memory.index'
23
- end
24
- end
25
-
26
- describe 'backup_directory' do
27
- it "returns the cache path's backup path" do
28
- basic.backup_directory('some/cache/path/to/file').should == 'some/cache/path/to/backup'
29
- end
30
- end
31
-
32
20
  describe 'to_s' do
33
21
  it 'returns the cache path with the default file extension' do
34
22
  basic.to_s.should == 'Picky::Backends::File::Basic(some/cache/path/to/file.file.index,some/cache/path/to/file.file_mapping.index.memory.json)'
35
23
  end
36
24
  end
37
25
  end
38
-
26
+
39
27
  context 'with options' do
40
28
  let(:basic) do
41
29
  described_class.new 'some/cache/path/to/file',
@@ -48,12 +36,12 @@ describe Picky::Backends::File::Basic do
48
36
  basic.empty.should == []
49
37
  end
50
38
  end
51
-
39
+
52
40
  describe 'initial' do
53
41
  it 'returns the container that is used for indexing' do
54
42
  basic.initial.should == []
55
43
  end
56
44
  end
57
45
  end
58
-
46
+
59
47
  end
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Picky::Backends::Memory::Basic do
4
-
4
+
5
5
  context 'without options' do
6
6
  let(:basic) { described_class.new 'some/cache/path/to/file' }
7
7
 
@@ -10,32 +10,20 @@ describe Picky::Backends::Memory::Basic do
10
10
  basic.empty.should == {}
11
11
  end
12
12
  end
13
-
13
+
14
14
  describe 'initial' do
15
15
  it 'returns the container that is used for indexing' do
16
16
  basic.initial.should == {}
17
17
  end
18
18
  end
19
19
 
20
- describe 'backup_file_path_of' do
21
- it 'returns a backup path relative to the path' do
22
- basic.backup_file_path_of('some/path/to/some.memory.index').should == 'some/path/to/backup/some.memory.index'
23
- end
24
- end
25
-
26
- describe 'backup_directory' do
27
- it "returns the cache path's backup path" do
28
- basic.backup_directory('some/cache/path/to/file').should == 'some/cache/path/to/backup'
29
- end
30
- end
31
-
32
20
  describe 'to_s' do
33
21
  it 'returns the cache path with the default file extension' do
34
22
  basic.to_s.should == 'Picky::Backends::Memory::Basic(some/cache/path/to/file.memory.index)'
35
23
  end
36
24
  end
37
25
  end
38
-
26
+
39
27
  context 'with options' do
40
28
  let(:basic) do
41
29
  described_class.new 'some/cache/path/to/file',
@@ -48,12 +36,12 @@ describe Picky::Backends::Memory::Basic do
48
36
  basic.empty.should == []
49
37
  end
50
38
  end
51
-
39
+
52
40
  describe 'initial' do
53
41
  it 'returns the container that is used for indexing' do
54
42
  basic.initial.should == []
55
43
  end
56
44
  end
57
45
  end
58
-
46
+
59
47
  end
@@ -1,19 +1,18 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Picky::Backends::Redis::Basic do
4
-
4
+
5
5
  let(:client) { stub :client }
6
-
6
+
7
7
  context 'without options' do
8
8
  let(:index) { described_class.new client, :some_namespace }
9
9
 
10
- describe 'load, retrieve, backup, delete' do
10
+ describe 'load, retrieve, delete' do
11
11
  it 'is nothing they do (at least on the backend)' do
12
12
  index.should_receive(:client).never
13
13
 
14
14
  index.load
15
15
  index.retrieve
16
- index.backup
17
16
  index.delete
18
17
  end
19
18
  end
@@ -30,59 +29,13 @@ describe Picky::Backends::Redis::Basic do
30
29
  end
31
30
  end
32
31
 
33
- describe 'cache_small?' do
34
- context 'size 0' do
35
- before(:each) do
36
- index.stub! :size => 0
37
- end
38
- it 'is small' do
39
- index.cache_small?.should == true
40
- end
41
- end
42
- context 'size 1' do
43
- before(:each) do
44
- index.stub! :size => 1
45
- end
46
- it 'is not small' do
47
- index.cache_small?.should == false
48
- end
49
- end
50
- end
51
-
52
- describe 'cache_ok?' do
53
- context 'size 0' do
54
- before(:each) do
55
- index.stub! :size => 0
56
- end
57
- it 'is not ok' do
58
- index.cache_ok?.should == false
59
- end
60
- end
61
- context 'size 1' do
62
- before(:each) do
63
- index.stub! :size => 1
64
- end
65
- it 'is ok' do
66
- index.cache_ok?.should == true
67
- end
68
- end
69
- end
70
-
71
- describe "size" do
72
- it 'delegates to the backend' do
73
- client.should_receive(:dbsize).once.with
74
-
75
- index.size
76
- end
77
- end
78
-
79
32
  describe 'to_s' do
80
33
  it 'returns the cache path with the default file extension' do
81
34
  index.to_s.should == 'Picky::Backends::Redis::Basic(some_namespace:*)'
82
35
  end
83
36
  end
84
37
  end
85
-
38
+
86
39
  context 'with options' do
87
40
  let(:index) do
88
41
  described_class.new client,
@@ -103,5 +56,5 @@ describe Picky::Backends::Redis::Basic do
103
56
  end
104
57
  end
105
58
  end
106
-
59
+
107
60
  end
@@ -0,0 +1,80 @@
1
+ require 'spec_helper'
2
+
3
+ require 'sqlite3'
4
+
5
+ describe Picky::Backends::Sqlite::DB do
6
+
7
+ context 'hash-based indexes' do
8
+ let(:db) { described_class.new 'some/cache/path/to/file' }
9
+
10
+ describe 'dump' do
11
+ it 'delegates to the given hash' do
12
+ hash = stub :hash
13
+
14
+ db.should_receive(:dump_sqlite).once.with hash
15
+
16
+ db.dump hash
17
+ end
18
+ end
19
+
20
+ describe 'dump_sqlite' do
21
+ let(:client) { stub :client }
22
+ before(:each) do
23
+ db.stub! :db => client
24
+ end
25
+ it 'initializes the client' do
26
+ client.stub! :execute
27
+
28
+ db.should_receive(:lazily_initialize_client).once.with
29
+
30
+ db.dump_sqlite Hash.new
31
+ end
32
+ it 'executes something' do
33
+ db.stub! :lazily_initialize_client
34
+
35
+ client.should_receive(:execute).at_least(1).times
36
+
37
+ db.dump_sqlite Hash.new
38
+ end
39
+ it 'inserts keys and values' do
40
+ db.stub! :lazily_initialize_client
41
+ client.stub! :execute # We only want to test the insert statements.
42
+
43
+ client.should_receive(:execute).once.with 'insert into key_value values (?,?)', 'a', '[1,2,3]'
44
+ client.should_receive(:execute).once.with 'insert into key_value values (?,?)', 'b', '[4,5,6]'
45
+
46
+ db.dump_sqlite :a => [1,2,3], :b => [4,5,6]
47
+ end
48
+ end
49
+
50
+ describe 'load' do
51
+ it 'returns a copy of itself' do
52
+ db.load.should == db
53
+ end
54
+ it 'initializes the client' do
55
+ db.should_receive(:lazily_initialize_client).once.with
56
+
57
+ db.load
58
+ end
59
+ end
60
+
61
+ describe 'empty' do
62
+ it 'returns the container that is used for indexing' do
63
+ db.empty.should == {}
64
+ end
65
+ end
66
+
67
+ describe 'initial' do
68
+ it 'is correct' do
69
+ db.initial.should == {}
70
+ end
71
+ end
72
+
73
+ describe 'to_s' do
74
+ it 'returns the cache path with the default file extension' do
75
+ db.to_s.should == 'Picky::Backends::Sqlite::DB(some/cache/path/to/file.sqlite3)'
76
+ end
77
+ end
78
+ end
79
+
80
+ end