picky 0.9.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/picky/indexes.rb CHANGED
@@ -128,8 +128,8 @@ module Indexes
128
128
  #
129
129
  def self.clear_caches
130
130
  each_bundle do |exact, partial|
131
- exact.delete_all
132
- partial.delete_all
131
+ exact.delete
132
+ partial.delete
133
133
  end
134
134
  end
135
135
 
data/lib/picky/loader.rb CHANGED
@@ -155,14 +155,20 @@ module Loader
155
155
  load_relative 'cacher/weights_generator'
156
156
  load_relative 'cacher/similarity_generator'
157
157
 
158
+ # Index file handling.
159
+ #
160
+ load_relative 'index/file/basic'
161
+ load_relative 'index/file/text'
162
+ load_relative 'index/file/marshal'
163
+ load_relative 'index/file/json'
164
+ load_relative 'index/files'
165
+
158
166
  # Index types.
159
167
  #
160
168
  load_relative 'index/bundle'
161
169
  load_relative 'index/category'
162
170
  load_relative 'index/type'
163
171
 
164
- load_relative 'index/bundle_checker'
165
-
166
172
  load_relative 'index/wrappers/exact_first'
167
173
 
168
174
  # Tokens.
@@ -3,10 +3,16 @@ module Sources
3
3
  class Delicious < Base
4
4
 
5
5
  def initialize username, password
6
- require 'www/delicious'
6
+ check_gem
7
7
  @username = username
8
8
  @password = password
9
9
  end
10
+ def check_gem
11
+ require 'www/delicious'
12
+ rescue LoadError
13
+ puts "Delicious gem missing!\nTo use the delicious source, you need to:\n 1. Add the following line to Gemfile:\n gem 'www-delicious'\n 2. Then, run:\n bundle update\n"
14
+ exit(1)
15
+ end
10
16
 
11
17
  # Harvests the data to index.
12
18
  #
@@ -17,14 +17,16 @@ class PickySearch < Application
17
17
  books_index = index :books,
18
18
  Sources::CSV.new(:title, :author, :isbn, :year, :publisher, :subjects, :file => 'app/library.csv'),
19
19
  # Use a database as source:
20
- # Sources::DB.new('SELECT id, title, author, isbn13 as isbn FROM books', :file => 'app/db.yml'),
20
+ # Sources::DB.new('SELECT id, title, author, isbn13 as isbn FROM books', :file => 'app/db.yml'),
21
+ # Or delicious:
22
+ # Sources::Delicious.new('username', 'password'), # offers title, tags, url fields.
21
23
  field(:title,
22
- :partial => Partial::Subtoken.new(:down_to => 1), # Index partial down to character 1 (default: -3),
23
- # e.g. florian -> floria, flori, flor, flo, fl, f
24
- # Like this, you'll find florian even when entering just an "f".
25
- :similarity => Similarity::DoubleLevenshtone.new(3)), # Up to three similar title word indexed.
26
- field(:author, :partial => Partial::Subtoken.new(:down_to => 1)),
27
- field(:isbn, :partial => Partial::None.new) # Partially searching on an ISBN makes not much sense, neither does similarity.
24
+ :partial => Partial::Substring.new(:from => 1), # Index substrings upwards from character 1 (default: -3),
25
+ # e.g. picky -> p, pi, pic, pick, picky
26
+ # Like this, you'll find picky even when entering just a "p".
27
+ :similarity => Similarity::DoubleLevenshtone.new(3)), # Up to three similar title word indexed (default: no similarity).
28
+ field(:author, :partial => Partial::Substring.new(:from => 1)),
29
+ field(:isbn, :partial => Partial::None.new) # Partial substring searching on an ISBN makes not much sense, neither does similarity.
28
30
 
29
31
  # Defines the maximum tokens (words) that pass through to the engine.
30
32
  #
@@ -3,13 +3,13 @@ require 'spec_helper'
3
3
  describe Cacher::Partial::Default do
4
4
 
5
5
  it "should be a subtoken" do
6
- Cacher::Partial::Default.should be_kind_of(Cacher::Partial::Subtoken)
6
+ Cacher::Partial::Default.should be_kind_of(Cacher::Partial::Substring)
7
7
  end
8
8
  it "should be a the right down to" do
9
- Cacher::Partial::Default.down_to.should == -3
9
+ Cacher::Partial::Default.from.should == -3
10
10
  end
11
11
  it "should be a the right starting at" do
12
- Cacher::Partial::Default.starting_at.should == -1
12
+ Cacher::Partial::Default.to.should == -1
13
13
  end
14
14
 
15
15
  end
@@ -1,14 +1,14 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Cacher::Partial::Subtoken do
3
+ describe Cacher::Partial::Substring do
4
4
 
5
- context 'default down_to' do
5
+ context 'default from' do
6
6
  before(:each) do
7
- @cacher = Cacher::Partial::Subtoken.new
7
+ @cacher = Cacher::Partial::Substring.new
8
8
  end
9
- describe 'down_to' do
9
+ describe 'from' do
10
10
  it 'should return the right value' do
11
- @cacher.down_to.should == 1
11
+ @cacher.from.should == 1
12
12
  end
13
13
  end
14
14
  describe 'generate_from' do
@@ -40,10 +40,10 @@ describe Cacher::Partial::Subtoken do
40
40
  end
41
41
  end
42
42
  end
43
- context 'down_to set' do
44
- describe 'negative down_to' do
43
+ context 'from set' do
44
+ describe 'negative from' do
45
45
  before(:each) do
46
- @cacher = Cacher::Partial::Subtoken.new :down_to => -2
46
+ @cacher = Cacher::Partial::Substring.new :from => -2
47
47
  end
48
48
  it 'should generate the right index' do
49
49
  @cacher.generate_from( :florian => [1], :flavia => [2] ).should == {
@@ -54,9 +54,9 @@ describe Cacher::Partial::Subtoken do
54
54
  }
55
55
  end
56
56
  end
57
- context "large down_to" do
57
+ context "large from" do
58
58
  before(:each) do
59
- @cacher = Cacher::Partial::Subtoken.new :down_to => 10
59
+ @cacher = Cacher::Partial::Substring.new :from => 10
60
60
  end
61
61
  describe 'generate_from' do
62
62
  it 'should generate the right index' do
@@ -68,18 +68,18 @@ describe Cacher::Partial::Subtoken do
68
68
  end
69
69
  end
70
70
  end
71
- context 'default starting_at' do
71
+ context 'default to' do
72
72
  before(:each) do
73
- @cacher = Cacher::Partial::Subtoken.new :down_to => 4
73
+ @cacher = Cacher::Partial::Substring.new :from => 4
74
74
  end
75
- describe 'starting_at' do
75
+ describe 'to' do
76
76
  it 'should return the right value' do
77
- @cacher.starting_at.should == -1
77
+ @cacher.to.should == -1
78
78
  end
79
79
  end
80
- describe 'down_to' do
80
+ describe 'from' do
81
81
  it 'should return the right value' do
82
- @cacher.down_to.should == 4
82
+ @cacher.from.should == 4
83
83
  end
84
84
  end
85
85
  describe 'generate_from' do
@@ -122,18 +122,18 @@ describe Cacher::Partial::Subtoken do
122
122
  end
123
123
  end
124
124
  end
125
- context 'starting_at set' do
125
+ context 'to set' do
126
126
  before(:each) do
127
- @cacher = Cacher::Partial::Subtoken.new :down_to => 4, :starting_at => -2
127
+ @cacher = Cacher::Partial::Substring.new :from => 4, :to => -2
128
128
  end
129
- describe 'starting_at' do
129
+ describe 'to' do
130
130
  it 'should return the right value' do
131
- @cacher.starting_at.should == -2
131
+ @cacher.to.should == -2
132
132
  end
133
133
  end
134
- describe 'down_to' do
134
+ describe 'from' do
135
135
  it 'should return the right value' do
136
- @cacher.down_to.should == 4
136
+ @cacher.from.should == 4
137
137
  end
138
138
  end
139
139
  describe 'generate_from' do
@@ -148,18 +148,18 @@ describe Cacher::Partial::Subtoken do
148
148
  end
149
149
  end
150
150
  end
151
- context 'starting_at set' do
151
+ context 'to set' do
152
152
  before(:each) do
153
- @cacher = Cacher::Partial::Subtoken.new :down_to => 4, :starting_at => 0
153
+ @cacher = Cacher::Partial::Substring.new :from => 4, :to => 0
154
154
  end
155
- describe 'starting_at' do
155
+ describe 'to' do
156
156
  it 'should return the right value' do
157
- @cacher.starting_at.should == 0
157
+ @cacher.to.should == 0
158
158
  end
159
159
  end
160
- describe 'down_to' do
160
+ describe 'from' do
161
161
  it 'should return the right value' do
162
- @cacher.down_to.should == 4
162
+ @cacher.from.should == 4
163
163
  end
164
164
  end
165
165
  describe 'generate_from' do
@@ -6,7 +6,7 @@ describe Cacher::PartialGenerator do
6
6
  it 'should generate the correct values with a given strategy' do
7
7
  generator = Cacher::PartialGenerator.new :meier => [1], :maier => [2]
8
8
 
9
- generator.generate(Cacher::Partial::Subtoken.new).should == {
9
+ generator.generate(Cacher::Partial::Substring.new).should == {
10
10
  :meier => [1],
11
11
  :meie => [1],
12
12
  :mei => [1],
@@ -21,7 +21,7 @@ describe Cacher::PartialGenerator do
21
21
  it 'should generate the correct values with a given specific strategy' do
22
22
  generator = Cacher::PartialGenerator.new :meier => [1], :maier => [2]
23
23
 
24
- generator.generate(Cacher::Partial::Subtoken.new(:down_to => 3)).should == {
24
+ generator.generate(Cacher::Partial::Substring.new(:from => 3)).should == {
25
25
  :meier => [1],
26
26
  :meie => [1],
27
27
  :mei => [1],
@@ -6,7 +6,7 @@ describe Hash do
6
6
  it 'uses the right file' do
7
7
  File.should_receive(:open).once.with('some/file/path.json', 'w')
8
8
 
9
- {}.dump_to_json 'some/file/path'
9
+ {}.dump_json 'some/file/path.json'
10
10
  end
11
11
  it "uses the right encoder" do
12
12
  file = stub :file
@@ -14,7 +14,7 @@ describe Hash do
14
14
 
15
15
  Yajl::Encoder.should_receive(:encode).once.with({ :some => :hash }, file)
16
16
 
17
- { :some => :hash }.dump_to_json 'unimportant'
17
+ { :some => :hash }.dump_json 'unimportant'
18
18
  end
19
19
  end
20
20
 
@@ -22,7 +22,7 @@ describe Hash do
22
22
  it 'uses the right file' do
23
23
  File.should_receive(:open).once.with('some/file/path.dump', 'w:binary')
24
24
 
25
- {}.dump_to_marshalled 'some/file/path'
25
+ {}.dump_marshalled 'some/file/path.dump'
26
26
  end
27
27
  it "uses the right encoder" do
28
28
  file = stub :file
@@ -30,7 +30,7 @@ describe Hash do
30
30
 
31
31
  Marshal.should_receive(:dump).once.with({ :some => :hash }, file)
32
32
 
33
- { :some => :hash }.dump_to_marshalled 'unimportant'
33
+ { :some => :hash }.dump_marshalled 'unimportant'
34
34
  end
35
35
  end
36
36
 
@@ -5,7 +5,7 @@ describe Index::Bundle do
5
5
  before(:each) do
6
6
  @category = stub :category, :name => :some_category
7
7
  @type = stub :type, :name => :some_type
8
- @partial_strategy = Cacher::Partial::Subtoken.new :down_to => 1
8
+ @partial_strategy = Cacher::Partial::Substring.new :from => 1
9
9
  @exact = Index::Bundle.new :some_name, @category, @type, @partial_strategy, nil, nil
10
10
  end
11
11
 
@@ -17,21 +17,7 @@ describe Index::Bundle do
17
17
  @index.identifier.should == 'some_name: some_type some_category'
18
18
  end
19
19
  end
20
-
21
- describe 'create_directory' do
22
- it 'should use makedirs to create the necessary directory structure' do
23
- FileUtils.should_receive(:mkdir_p).once.with 'some/search/root/index/test/some_type'
24
-
25
- @index.create_directory
26
- end
27
- end
28
-
29
- describe 'cache_directory' do
30
- it 'should be correct' do
31
- @index.cache_directory.should == 'some/search/root/index/test/some_type'
32
- end
33
- end
34
-
20
+
35
21
  describe 'initialize_index_for' do
36
22
  context 'token not yet assigned' do
37
23
  before(:each) do
@@ -127,17 +113,7 @@ describe Index::Bundle do
127
113
  @index.weight(:existing).should == :specific
128
114
  end
129
115
  end
130
-
131
- describe 'delete_all' do
132
- it 'should call delete with all paths' do
133
- @index.should_receive(:delete).once.with @index.index_cache_path
134
- @index.should_receive(:delete).once.with @index.similarity_cache_path
135
- @index.should_receive(:delete).once.with @index.weights_cache_path
136
-
137
- @index.delete_all
138
- end
139
- end
140
-
116
+
141
117
  describe 'load' do
142
118
  it 'should trigger loads' do
143
119
  @index.should_receive(:load_index).once.with
@@ -190,25 +166,56 @@ describe Index::Bundle do
190
166
  end
191
167
  end
192
168
 
193
- describe 'weights_cache_path' do
194
- it 'should return the correct file name' do
195
- @index.weights_cache_path.should == 'some/search/root/index/test/some_type/some_name_some_category_weights'
169
+ describe 'raise_unless_cache_exists' do
170
+ before(:each) do
171
+ @files = stub :files
172
+ @files.stub! :index_cache_ok? => true
173
+ @files.stub! :similarity_cache_ok? => true
174
+ @files.stub! :weights_cache_ok? => true
175
+ @files.stub! :index_cache_small? => false
176
+ @files.stub! :similarity_cache_small? => false
177
+ @files.stub! :weights_cache_small? => false
178
+
179
+ @index.stub! :files => @files
196
180
  end
197
- end
198
- describe 'similarity_cache_path' do
199
- it 'should return the correct file name' do
200
- @index.similarity_cache_path.should == 'some/search/root/index/test/some_type/some_name_some_category_similarity'
181
+ context 'weights cache missing' do
182
+ before(:each) do
183
+ @files.stub! :weights_cache_ok? => false
184
+ end
185
+ it 'should raise' do
186
+ lambda do
187
+ @index.raise_unless_cache_exists
188
+ end.should raise_error("weights cache for some_name: some_type some_category missing.")
189
+ end
201
190
  end
202
- end
203
- describe 'index_cache_path' do
204
- it 'should return the correct file name' do
205
- @index.index_cache_path.should == 'some/search/root/index/test/some_type/some_name_some_category_index'
191
+ context 'similarity cache missing' do
192
+ before(:each) do
193
+ @files.stub! :similarity_cache_ok? => false
194
+ end
195
+ it 'should raise' do
196
+ lambda do
197
+ @index.raise_unless_cache_exists
198
+ end.should raise_error("similarity cache for some_name: some_type some_category missing.")
199
+ end
200
+ end
201
+ context 'index cache missing' do
202
+ before(:each) do
203
+ @files.stub! :index_cache_ok? => false
204
+ end
205
+ it 'should raise' do
206
+ lambda do
207
+ @index.raise_unless_cache_exists
208
+ end.should raise_error("index cache for some_name: some_type some_category missing.")
209
+ end
206
210
  end
207
211
  end
208
-
212
+
209
213
  describe 'initialization' do
210
214
  before(:each) do
211
- @index = @index_class.new :some_name, :some_category, :some_type, :partial, :weights, :similarity
215
+ @category = stub :category, :name => :some_category
216
+ @type = stub :type, :name => :some_type
217
+
218
+ @index = @index_class.new :some_name, @category, @type, :partial, :weights, :similarity
212
219
  end
213
220
  it 'should initialize the index correctly' do
214
221
  @index.index.should == {}
@@ -220,13 +227,7 @@ describe Index::Bundle do
220
227
  @index.similarity.should == {}
221
228
  end
222
229
  it 'should initialize the name correctly' do
223
- @index.name.should == :some_name
224
- end
225
- it 'should initialize the name correctly' do
226
- @index.category.should == :some_category
227
- end
228
- it 'should initialize the name correctly' do
229
- @index.type.should == :some_type
230
+ @index.category.should == @category
230
231
  end
231
232
  it 'should initialize the partial strategy correctly' do
232
233
  @index.partial_strategy.should == :partial
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe Index::File::Basic do
4
+
5
+ before(:each) do
6
+ @file = Index::File::Basic.new "some/cache/path/to/file"
7
+ end
8
+
9
+ describe "backup_file_path_of" do
10
+ it "returns a backup path relative to the path" do
11
+ @file.backup_file_path_of('some/path/to/some.index').should == 'some/path/to/backup/some.index'
12
+ end
13
+ end
14
+
15
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe Index::File::JSON do
4
+
5
+ before(:each) do
6
+ @file = Index::File::JSON.new "some_cache_path"
7
+ end
8
+
9
+ describe "dump" do
10
+ it "delegates to the given hash" do
11
+ hash = stub :hash
12
+
13
+ hash.should_receive(:dump_json).once.with "some_cache_path.json"
14
+
15
+ @file.dump hash
16
+ end
17
+ end
18
+ describe "retrieve" do
19
+ it "raises" do
20
+ lambda do
21
+ @file.retrieve
22
+ end.should raise_error("Can't retrieve from marshalled file. Use text file.")
23
+ end
24
+ end
25
+
26
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe Index::File::Marshal do
4
+
5
+ before(:each) do
6
+ @file = Index::File::Marshal.new "some_cache_path"
7
+ end
8
+
9
+ describe "dump" do
10
+ it "delegates to the given hash" do
11
+ hash = stub :hash
12
+
13
+ hash.should_receive(:dump_marshalled).once.with "some_cache_path.dump"
14
+
15
+ @file.dump hash
16
+ end
17
+ end
18
+ describe "retrieve" do
19
+ it "raises" do
20
+ lambda do
21
+ @file.retrieve
22
+ end.should raise_error("Can't retrieve from marshalled file. Use text file.")
23
+ end
24
+ end
25
+
26
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe Index::File::Text do
4
+
5
+ before(:each) do
6
+ @file = Index::File::Text.new "some_cache_path"
7
+ end
8
+
9
+ describe "load" do
10
+ it "raises" do
11
+ lambda do
12
+ @file.load
13
+ end.should raise_error("Can't load from text file. Use JSON or Marshal.")
14
+ end
15
+ end
16
+ describe "dump" do
17
+ it "raises" do
18
+ lambda do
19
+ @file.dump :anything
20
+ end.should raise_error("Can't dump to text file. Use JSON or Marshal.")
21
+ end
22
+ end
23
+ describe "retrieve" do
24
+ it
25
+ end
26
+
27
+ end