picky 0.9.0 → 0.9.1
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/cacher/partial/default.rb +1 -1
- data/lib/picky/cacher/partial/subtoken.rb +18 -18
- data/lib/picky/cacher/partial_generator.rb +1 -1
- data/lib/picky/extensions/hash.rb +4 -4
- data/lib/picky/extensions/symbol.rb +9 -9
- data/lib/picky/index/bundle.rb +58 -133
- data/lib/picky/index/file/basic.rb +67 -0
- data/lib/picky/index/file/json.rb +24 -0
- data/lib/picky/index/file/marshal.rb +24 -0
- data/lib/picky/index/file/text.rb +28 -0
- data/lib/picky/index/files.rb +135 -0
- data/lib/picky/indexers/base.rb +4 -0
- data/lib/picky/indexes.rb +2 -2
- data/lib/picky/loader.rb +8 -2
- data/lib/picky/sources/delicious.rb +7 -1
- data/project_prototype/app/application.rb +9 -7
- data/spec/lib/cacher/partial/default_spec.rb +3 -3
- data/spec/lib/cacher/partial/subtoken_spec.rb +28 -28
- data/spec/lib/cacher/partial_generator_spec.rb +2 -2
- data/spec/lib/extensions/hash_spec.rb +4 -4
- data/spec/lib/index/bundle_partial_generation_speed_spec.rb +1 -1
- data/spec/lib/index/bundle_spec.rb +47 -46
- data/spec/lib/index/file/basic_spec.rb +15 -0
- data/spec/lib/index/file/json_spec.rb +26 -0
- data/spec/lib/index/file/marshal_spec.rb +26 -0
- data/spec/lib/index/file/text_spec.rb +27 -0
- data/spec/lib/index/files_spec.rb +186 -0
- data/spec/lib/index/type_spec.rb +5 -2
- data/spec/lib/query/combinator_spec.rb +5 -3
- data/spec/lib/sources/delicious_spec.rb +9 -1
- metadata +18 -6
- data/lib/picky/index/bundle_checker.rb +0 -58
- data/spec/lib/index/bundle_checker_spec.rb +0 -67
data/lib/picky/indexes.rb
CHANGED
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
|
-
|
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::
|
23
|
-
# e.g.
|
24
|
-
# Like this, you'll find
|
25
|
-
:similarity => Similarity::DoubleLevenshtone.new(3)), # Up to three similar title word indexed.
|
26
|
-
field(:author, :partial => Partial::
|
27
|
-
field(:isbn, :partial => Partial::None.new) #
|
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::
|
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.
|
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.
|
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::
|
3
|
+
describe Cacher::Partial::Substring do
|
4
4
|
|
5
|
-
context 'default
|
5
|
+
context 'default from' do
|
6
6
|
before(:each) do
|
7
|
-
@cacher = Cacher::Partial::
|
7
|
+
@cacher = Cacher::Partial::Substring.new
|
8
8
|
end
|
9
|
-
describe '
|
9
|
+
describe 'from' do
|
10
10
|
it 'should return the right value' do
|
11
|
-
@cacher.
|
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 '
|
44
|
-
describe 'negative
|
43
|
+
context 'from set' do
|
44
|
+
describe 'negative from' do
|
45
45
|
before(:each) do
|
46
|
-
@cacher = Cacher::Partial::
|
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
|
57
|
+
context "large from" do
|
58
58
|
before(:each) do
|
59
|
-
@cacher = Cacher::Partial::
|
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
|
71
|
+
context 'default to' do
|
72
72
|
before(:each) do
|
73
|
-
@cacher = Cacher::Partial::
|
73
|
+
@cacher = Cacher::Partial::Substring.new :from => 4
|
74
74
|
end
|
75
|
-
describe '
|
75
|
+
describe 'to' do
|
76
76
|
it 'should return the right value' do
|
77
|
-
@cacher.
|
77
|
+
@cacher.to.should == -1
|
78
78
|
end
|
79
79
|
end
|
80
|
-
describe '
|
80
|
+
describe 'from' do
|
81
81
|
it 'should return the right value' do
|
82
|
-
@cacher.
|
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 '
|
125
|
+
context 'to set' do
|
126
126
|
before(:each) do
|
127
|
-
@cacher = Cacher::Partial::
|
127
|
+
@cacher = Cacher::Partial::Substring.new :from => 4, :to => -2
|
128
128
|
end
|
129
|
-
describe '
|
129
|
+
describe 'to' do
|
130
130
|
it 'should return the right value' do
|
131
|
-
@cacher.
|
131
|
+
@cacher.to.should == -2
|
132
132
|
end
|
133
133
|
end
|
134
|
-
describe '
|
134
|
+
describe 'from' do
|
135
135
|
it 'should return the right value' do
|
136
|
-
@cacher.
|
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 '
|
151
|
+
context 'to set' do
|
152
152
|
before(:each) do
|
153
|
-
@cacher = Cacher::Partial::
|
153
|
+
@cacher = Cacher::Partial::Substring.new :from => 4, :to => 0
|
154
154
|
end
|
155
|
-
describe '
|
155
|
+
describe 'to' do
|
156
156
|
it 'should return the right value' do
|
157
|
-
@cacher.
|
157
|
+
@cacher.to.should == 0
|
158
158
|
end
|
159
159
|
end
|
160
|
-
describe '
|
160
|
+
describe 'from' do
|
161
161
|
it 'should return the right value' do
|
162
|
-
@cacher.
|
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::
|
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::
|
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
|
-
{}.
|
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 }.
|
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
|
-
{}.
|
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 }.
|
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::
|
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 '
|
194
|
-
|
195
|
-
@
|
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
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
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
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
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
|
-
@
|
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.
|
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
|