fuzzzy 0.0.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.
@@ -0,0 +1,165 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fuzzzy::Mongoid::Index do
4
+ let(:context){{
5
+ :index_name => 'indexedcity:name',
6
+ :method => :soundex
7
+ }}
8
+
9
+ describe '.define_fuzzzy_index' do
10
+ context 'without index' do
11
+ let!(:city){City}
12
+ specify{city.fuzzzy_indexes.should be_nil}
13
+ specify{city.has_fuzzzy_indexes?.should be_false}
14
+ end
15
+
16
+ context 'with default index' do
17
+ let!(:city){IndexedCity}
18
+ specify{city.fuzzzy_indexes.should be_instance_of(Hash)}
19
+ specify{city.fuzzzy_indexes.values.should have(1).index}
20
+ specify{city.fuzzzy_indexes[:name].should == context}
21
+ specify{city.has_fuzzzy_indexes?.should be_true}
22
+ end
23
+ end
24
+
25
+ describe '.indexer' do
26
+ specify{IndexedCity.indexer(:soundex).should be_instance_of(Fuzzzy::Soundex::Indexer)}
27
+ specify{City.indexer(:soundex).should be_nil}
28
+ specify do
29
+ lambda{
30
+ IndexedCity.indexer(:blablabla)
31
+ }.should raise_error
32
+ end
33
+ end
34
+
35
+ describe '.searcher' do
36
+ specify{IndexedCity.searcher(:soundex).should be_instance_of(Fuzzzy::Soundex::Searcher)}
37
+ specify{City.searcher(:soundex).should be_nil}
38
+ specify do
39
+ lambda{
40
+ IndexedCity.searcher(:blablabla)
41
+ }.should raise_error
42
+ end
43
+ end
44
+
45
+ describe '.search_by' do
46
+ let(:query){'String'}
47
+
48
+ context 'by indexed field' do
49
+ let(:searcher){mock(:searcher)}
50
+
51
+ before do
52
+ searcher.should_receive(:search).with(search_context)
53
+ IndexedCity.stub(:searcher => searcher)
54
+ end
55
+
56
+ context 'with default context' do
57
+ let(:search_context){context.merge(:query => query)}
58
+ specify{IndexedCity.search_by(:name, query)}
59
+ end
60
+
61
+ context 'with custom context' do
62
+ let(:search_context){context.merge(
63
+ :query => query,
64
+ :only_ids => true,
65
+ :sort_method => :alpha,
66
+ :distance => 3
67
+ )}
68
+
69
+ specify{IndexedCity.search_by(:name, query, {
70
+ :only_ids => true,
71
+ :sort_method => :alpha,
72
+ :distance => 3
73
+ })}
74
+ end
75
+ end
76
+
77
+ context 'by unindexed field' do
78
+ specify do
79
+ lambda{
80
+ IndexedCity.search_by(:country, query)
81
+ }.should raise_error
82
+ end
83
+ end
84
+ end
85
+
86
+ context do
87
+ let(:model){IndexedCity.new(:id => BSON::ObjectId.new, :name => 'Moscow', :country => 'Russia')}
88
+ let(:indexer){mock(:indexer)}
89
+
90
+ describe '.create_fuzzzy_indexes' do
91
+ context do
92
+ let(:index_context){context.merge(
93
+ :id => model.id,
94
+ :dictionary_string => model.name
95
+ )}
96
+
97
+ before do
98
+ indexer.should_receive(:create_index).with(index_context)
99
+ IndexedCity.stub(:indexer => indexer)
100
+ end
101
+
102
+ specify{model.create_fuzzzy_indexes{}}
103
+ end
104
+
105
+ context 'with multi fields index' do
106
+ before do
107
+ IndexedCity.define_fuzzzy_index(:country)
108
+ indexer.should_receive(:create_index).exactly(2).times
109
+ IndexedCity.stub(:indexer => indexer)
110
+ end
111
+
112
+ after do
113
+ IndexedCity.clear_fuzzzy_index(:country)
114
+ end
115
+
116
+ specify{model.create_fuzzzy_indexes{}}
117
+ end
118
+
119
+ context 'with empty changed attributes' do
120
+ let(:index_context){context.merge(
121
+ :id => model.id,
122
+ :dictionary_string => model.name
123
+ )}
124
+
125
+ before do
126
+ model.stub(:changed => [])
127
+ indexer.should_not_receive(:create_index)
128
+ IndexedCity.stub(:indexer => indexer)
129
+ end
130
+
131
+ specify{model.create_fuzzzy_indexes{}}
132
+ end
133
+ end
134
+
135
+ describe '.delete_fuzzzy_indexes' do
136
+ context do
137
+ let(:index_context){context.merge(
138
+ :id => model.id,
139
+ :dictionary_string => model.name
140
+ )}
141
+
142
+ before do
143
+ indexer.should_receive(:delete_index).with(index_context)
144
+ IndexedCity.stub(:indexer => indexer)
145
+ end
146
+
147
+ specify{model.delete_fuzzzy_indexes{}}
148
+ end
149
+
150
+ context 'with multi fields index' do
151
+ before do
152
+ IndexedCity.define_fuzzzy_index(:country)
153
+ indexer.should_receive(:delete_index).exactly(2).times
154
+ IndexedCity.stub(:indexer => indexer)
155
+ end
156
+
157
+ after do
158
+ IndexedCity.clear_fuzzzy_index(:country)
159
+ end
160
+
161
+ specify{model.delete_fuzzzy_indexes{}}
162
+ end
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ class TestRedis
4
+ include Fuzzzy::Redis
5
+
6
+ def index_type
7
+ 'index_type'
8
+ end
9
+
10
+ def index_name
11
+ 'model_name:field'
12
+ end
13
+
14
+ def context
15
+ {}
16
+ end
17
+ end
18
+
19
+ class TestRedis2
20
+ include Fuzzzy::Redis
21
+ end
22
+
23
+
24
+ describe Fuzzzy::Redis do
25
+ subject{TestRedis.new}
26
+
27
+ describe '#shared_key' do
28
+ specify{subject.shared_key.should == 'fuzzzy:model_name:field'}
29
+ end
30
+
31
+ describe '#index_key' do
32
+ specify{subject.index_key('key1').should == 'fuzzzy:model_name:field:index_type:key1'}
33
+ specify{subject.index_key('key1', 'key2').should == 'fuzzzy:model_name:field:index_type:key1:key2'}
34
+ specify{subject.index_key('key1', 2).should == 'fuzzzy:model_name:field:index_type:key1:2'}
35
+ specify do
36
+ lambda{
37
+ subject.index_key
38
+ }.should raise_error
39
+ end
40
+ context do
41
+ subject{TestRedis2.new}
42
+ specify do
43
+ lambda{
44
+ subject.index_key('key1')
45
+ }.should raise_error
46
+ end
47
+ specify do
48
+ lambda{
49
+ subject.index_key('key1', 'key2')
50
+ }.should raise_error
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fuzzzy::Soundex::Indexer do
4
+ let(:indexer){Fuzzzy::Soundex::Indexer.new}
5
+ let(:context){{
6
+ :index_name => 'city:name',
7
+ :method => :soundex,
8
+ :dictionary_string => dictionary_string,
9
+ :id => id
10
+ }}
11
+ let(:dictionary_string){'moscow'}
12
+ let(:soundex){Text::Soundex.soundex(dictionary_string)}
13
+ let(:id){'12345'}
14
+
15
+ before do
16
+ keys = Fuzzzy.redis.keys("*")
17
+ Fuzzzy.redis.del(*keys) if keys.length > 1
18
+ end
19
+
20
+ describe '.create_index' do
21
+ before do
22
+ indexer.create_index(context)
23
+ end
24
+
25
+ specify{Fuzzzy.redis.smembers('fuzzzy:city:name:soundex_i:' + soundex).should == [id]}
26
+ specify{Fuzzzy.redis.get('fuzzzy:city:name:dictionary:' + id).should == dictionary_string}
27
+ specify{Fuzzzy.redis.hgetall(Fuzzzy::Redis.counter_key).should == {'city:name' => '1'}}
28
+ end
29
+
30
+ describe '.delete_index' do
31
+ before do
32
+ indexer.create_index(context)
33
+ indexer.delete_index(context)
34
+ end
35
+
36
+ specify{Fuzzzy.redis.exists('fuzzzy:city:name:soundex_i:' + soundex).should be_false}
37
+ specify{Fuzzzy.redis.exists('fuzzzy:city:name:dictionary:' + id).should be_false}
38
+ specify{Fuzzzy.redis.hgetall(Fuzzzy::Redis.counter_key).should == {'city:name' => '0'}}
39
+ end
40
+ end
@@ -0,0 +1,63 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fuzzzy::Soundex::Searcher do
4
+ let(:searcher){Fuzzzy::Soundex::Searcher.new}
5
+ let(:context){{
6
+ :index_name => 'city:name',
7
+ :method => :soundex,
8
+ :query => query_string
9
+ }}
10
+
11
+ before do
12
+ keys = Fuzzzy.redis.keys("*")
13
+ Fuzzzy.redis.del(*keys) if keys.length > 1
14
+ end
15
+
16
+ def add_index id, dictionary_string
17
+ Fuzzzy.redis.sadd('fuzzzy:city:name:soundex_i:' + Text::Soundex.soundex(dictionary_string), id)
18
+ Fuzzzy.redis.set('fuzzzy:city:name:dictionary:' + id, dictionary_string)
19
+ end
20
+
21
+ describe '#search' do
22
+ context 'single word' do
23
+ before do
24
+ add_index(id, dictionary_string)
25
+ end
26
+
27
+ let(:query_string){'mascow'}
28
+ let(:dictionary_string){'moscow'}
29
+ let(:id){'12345'}
30
+
31
+ specify{searcher.search(context).should == [id]}
32
+ end
33
+
34
+ context 'many words' do
35
+ before do
36
+ add_index('12345', 'moscow')
37
+ add_index('12346', 'piterburger')
38
+ add_index('12347', 'piterberg')
39
+ add_index('12348', 'piterburg')
40
+ add_index('12349', 'pitsburg')
41
+ add_index('12350', 'moscowcity')
42
+ end
43
+
44
+ let(:query_string){'mascow'}
45
+
46
+ specify{searcher.search(context).should == ['12345']}
47
+ specify{searcher.search(context.merge(:query => 'mascw')).should == ['12345']}
48
+ specify{searcher.search(context.merge(:query => 'peterberg')).should == ['12346', '12347', '12348']}
49
+ specify{searcher.search(context.merge(
50
+ :query => 'piterburg',
51
+ :sort_by => :distance
52
+ )).should == ['12348', '12347', '12346']}
53
+ specify{searcher.search(context.merge(
54
+ :query => 'piterburg',
55
+ :sort_by => :alpha
56
+ )).should == ['12347', '12348', '12346']}
57
+ specify{searcher.search(context.merge(
58
+ :query => 'piterburg',
59
+ :distance => 0
60
+ )).should == ['12348']}
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,22 @@
1
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
2
+ ENV['RACK_ENV'] = 'test'
3
+ require "rspec"
4
+ require 'mongoid'
5
+ require 'fuzzzy'
6
+ require Fuzzzy.root.join('spec', 'models', 'city')
7
+ require Fuzzzy.root.join('spec', 'models', 'indexed_city')
8
+
9
+ Fuzzzy.redis = Redis.new(:host => 'localhost', :database => 10)
10
+ Fuzzzy.logger = Mongoid.logger = nil
11
+ Mongoid.load!(Fuzzzy.root.join('spec', 'config', 'mongoid.yml'))
12
+
13
+ RSpec.configure do |config|
14
+ config.mock_with :rspec
15
+ config.after :suite do
16
+ Mongoid.master.collections.select{|c| c.name !~ /system/ }.each(&:drop)
17
+ keys = Fuzzzy.redis.keys("*")
18
+ if keys.length > 1
19
+ Fuzzzy.redis.del(*keys)
20
+ end
21
+ end
22
+ end
metadata ADDED
@@ -0,0 +1,325 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fuzzzy
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - Undr
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2012-07-19 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rspec
17
+ requirement: &id001 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: "2"
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
27
+ name: yard
28
+ requirement: &id002 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 0.6.0
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: *id002
37
+ - !ruby/object:Gem::Dependency
38
+ name: ruby-debug19
39
+ requirement: &id003 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: "0"
45
+ type: :development
46
+ prerelease: false
47
+ version_requirements: *id003
48
+ - !ruby/object:Gem::Dependency
49
+ name: bson_ext
50
+ requirement: &id004 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: "0"
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: *id004
59
+ - !ruby/object:Gem::Dependency
60
+ name: mongoid
61
+ requirement: &id005 !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: "0"
67
+ type: :development
68
+ prerelease: false
69
+ version_requirements: *id005
70
+ - !ruby/object:Gem::Dependency
71
+ name: pry
72
+ requirement: &id006 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: "0"
78
+ type: :development
79
+ prerelease: false
80
+ version_requirements: *id006
81
+ - !ruby/object:Gem::Dependency
82
+ name: ruby-prof
83
+ requirement: &id007 !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: "0"
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: *id007
92
+ - !ruby/object:Gem::Dependency
93
+ name: bundler
94
+ requirement: &id008 !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: "0"
100
+ type: :runtime
101
+ prerelease: false
102
+ version_requirements: *id008
103
+ - !ruby/object:Gem::Dependency
104
+ name: rake
105
+ requirement: &id009 !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: "0"
111
+ type: :runtime
112
+ prerelease: false
113
+ version_requirements: *id009
114
+ - !ruby/object:Gem::Dependency
115
+ name: activesupport
116
+ requirement: &id010 !ruby/object:Gem::Requirement
117
+ none: false
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: "0"
122
+ type: :runtime
123
+ prerelease: false
124
+ version_requirements: *id010
125
+ - !ruby/object:Gem::Dependency
126
+ name: eventmachine
127
+ requirement: &id011 !ruby/object:Gem::Requirement
128
+ none: false
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: "0"
133
+ type: :runtime
134
+ prerelease: false
135
+ version_requirements: *id011
136
+ - !ruby/object:Gem::Dependency
137
+ name: yajl-ruby
138
+ requirement: &id012 !ruby/object:Gem::Requirement
139
+ none: false
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ version: "0"
144
+ type: :runtime
145
+ prerelease: false
146
+ version_requirements: *id012
147
+ - !ruby/object:Gem::Dependency
148
+ name: levenshtein-ffi
149
+ requirement: &id013 !ruby/object:Gem::Requirement
150
+ none: false
151
+ requirements:
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ version: "0"
155
+ type: :runtime
156
+ prerelease: false
157
+ version_requirements: *id013
158
+ - !ruby/object:Gem::Dependency
159
+ name: text
160
+ requirement: &id014 !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: "0"
166
+ type: :runtime
167
+ prerelease: false
168
+ version_requirements: *id014
169
+ - !ruby/object:Gem::Dependency
170
+ name: grape
171
+ requirement: &id015 !ruby/object:Gem::Requirement
172
+ none: false
173
+ requirements:
174
+ - - ">="
175
+ - !ruby/object:Gem::Version
176
+ version: "0"
177
+ type: :runtime
178
+ prerelease: false
179
+ version_requirements: *id015
180
+ - !ruby/object:Gem::Dependency
181
+ name: hiredis
182
+ requirement: &id016 !ruby/object:Gem::Requirement
183
+ none: false
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: "0"
188
+ type: :runtime
189
+ prerelease: false
190
+ version_requirements: *id016
191
+ - !ruby/object:Gem::Dependency
192
+ name: redis
193
+ requirement: &id017 !ruby/object:Gem::Requirement
194
+ none: false
195
+ requirements:
196
+ - - ">="
197
+ - !ruby/object:Gem::Version
198
+ version: "0"
199
+ type: :runtime
200
+ prerelease: false
201
+ version_requirements: *id017
202
+ - !ruby/object:Gem::Dependency
203
+ name: daemons
204
+ requirement: &id018 !ruby/object:Gem::Requirement
205
+ none: false
206
+ requirements:
207
+ - - ">="
208
+ - !ruby/object:Gem::Version
209
+ version: "0"
210
+ type: :runtime
211
+ prerelease: false
212
+ version_requirements: *id018
213
+ - !ruby/object:Gem::Dependency
214
+ name: ZenTest
215
+ requirement: &id019 !ruby/object:Gem::Requirement
216
+ none: false
217
+ requirements:
218
+ - - "="
219
+ - !ruby/object:Gem::Version
220
+ version: 4.5.0
221
+ type: :runtime
222
+ prerelease: false
223
+ version_requirements: *id019
224
+ - !ruby/object:Gem::Dependency
225
+ name: RubyInline
226
+ requirement: &id020 !ruby/object:Gem::Requirement
227
+ none: false
228
+ requirements:
229
+ - - ">="
230
+ - !ruby/object:Gem::Version
231
+ version: "0"
232
+ type: :runtime
233
+ prerelease: false
234
+ version_requirements: *id020
235
+ description: Fuzzy Search client and server
236
+ email:
237
+ - lilipoper@gmail.com
238
+ executables: []
239
+
240
+ extensions: []
241
+
242
+ extra_rdoc_files: []
243
+
244
+ files:
245
+ - .gitignore
246
+ - .rspec
247
+ - .travis.yml
248
+ - Gemfile
249
+ - README.md
250
+ - Rakefile
251
+ - benchmark/data/cities.csv
252
+ - benchmark/fuzzzy_benchmark.rb
253
+ - benchmark/test_ngram.rb
254
+ - benchmark/test_soundex.rb
255
+ - config.ru
256
+ - dictionary/en_stopwords.yml
257
+ - fuzzzy.gemspec
258
+ - lib/fuzzzy.rb
259
+ - lib/fuzzzy/index.rb
260
+ - lib/fuzzzy/methods/indexer.rb
261
+ - lib/fuzzzy/methods/method_base.rb
262
+ - lib/fuzzzy/methods/ngram/base.rb
263
+ - lib/fuzzzy/methods/ngram/indexer.rb
264
+ - lib/fuzzzy/methods/ngram/searcher.rb
265
+ - lib/fuzzzy/methods/soundex/base.rb
266
+ - lib/fuzzzy/methods/soundex/indexer.rb
267
+ - lib/fuzzzy/methods/soundex/searcher.rb
268
+ - lib/fuzzzy/orm/mongoid/index.rb
269
+ - lib/fuzzzy/redis.rb
270
+ - lib/fuzzzy/server/http.rb
271
+ - lib/fuzzzy/version.rb
272
+ - spec/config/mongoid.yml
273
+ - spec/models/city.rb
274
+ - spec/models/indexed_city.rb
275
+ - spec/ngram/indexer_spec.rb
276
+ - spec/ngram/searcher_spec.rb
277
+ - spec/orm/mongoid/index_spec.rb
278
+ - spec/redis_spec.rb
279
+ - spec/soundex/indexer_spec.rb
280
+ - spec/soundex/searcher_spec.rb
281
+ - spec/spec_helper.rb
282
+ homepage: http://github.com/undr/fuzzzy
283
+ licenses: []
284
+
285
+ post_install_message:
286
+ rdoc_options: []
287
+
288
+ require_paths:
289
+ - lib
290
+ required_ruby_version: !ruby/object:Gem::Requirement
291
+ none: false
292
+ requirements:
293
+ - - ">="
294
+ - !ruby/object:Gem::Version
295
+ hash: -1332638981100280004
296
+ segments:
297
+ - 0
298
+ version: "0"
299
+ required_rubygems_version: !ruby/object:Gem::Requirement
300
+ none: false
301
+ requirements:
302
+ - - ">="
303
+ - !ruby/object:Gem::Version
304
+ hash: -1332638981100280004
305
+ segments:
306
+ - 0
307
+ version: "0"
308
+ requirements: []
309
+
310
+ rubyforge_project: fuzzzy
311
+ rubygems_version: 1.8.21
312
+ signing_key:
313
+ specification_version: 3
314
+ summary: Fuzzy Search client and server
315
+ test_files:
316
+ - spec/config/mongoid.yml
317
+ - spec/models/city.rb
318
+ - spec/models/indexed_city.rb
319
+ - spec/ngram/indexer_spec.rb
320
+ - spec/ngram/searcher_spec.rb
321
+ - spec/orm/mongoid/index_spec.rb
322
+ - spec/redis_spec.rb
323
+ - spec/soundex/indexer_spec.rb
324
+ - spec/soundex/searcher_spec.rb
325
+ - spec/spec_helper.rb