fuzzy_match 1.5.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +8 -8
  2. data/.rspec +2 -0
  3. data/CHANGELOG +14 -0
  4. data/Gemfile +8 -0
  5. data/README.markdown +58 -38
  6. data/Rakefile +0 -9
  7. data/bin/fuzzy_match +106 -0
  8. data/fuzzy_match.gemspec +4 -4
  9. data/groupings-screenshot.png +0 -0
  10. data/highlevel.graffle +0 -0
  11. data/highlevel.png +0 -0
  12. data/lib/fuzzy_match/record.rb +58 -0
  13. data/lib/fuzzy_match/result.rb +11 -8
  14. data/lib/fuzzy_match/rule/grouping.rb +70 -12
  15. data/lib/fuzzy_match/rule/identity.rb +3 -3
  16. data/lib/fuzzy_match/rule.rb +1 -1
  17. data/lib/fuzzy_match/score/amatch.rb +0 -4
  18. data/lib/fuzzy_match/score/pure_ruby.rb +2 -8
  19. data/lib/fuzzy_match/score.rb +4 -0
  20. data/lib/fuzzy_match/similarity.rb +10 -32
  21. data/lib/fuzzy_match/version.rb +1 -1
  22. data/lib/fuzzy_match.rb +78 -94
  23. data/{test/test_amatch.rb → spec/amatch_spec.rb} +1 -2
  24. data/{test/test_cache.rb → spec/cache_spec.rb} +7 -7
  25. data/spec/foo.rb +9 -0
  26. data/spec/fuzzy_match_spec.rb +354 -0
  27. data/spec/grouping_spec.rb +60 -0
  28. data/spec/identity_spec.rb +29 -0
  29. data/{test/test_wrapper.rb → spec/record_spec.rb} +3 -7
  30. data/spec/spec_helper.rb +21 -0
  31. metadata +56 -50
  32. data/bin/fuzzy_match_checker +0 -71
  33. data/examples/bts_aircraft/5-2-A.htm +0 -10305
  34. data/examples/bts_aircraft/5-2-B.htm +0 -9576
  35. data/examples/bts_aircraft/5-2-D.htm +0 -7094
  36. data/examples/bts_aircraft/5-2-E.htm +0 -2349
  37. data/examples/bts_aircraft/5-2-G.htm +0 -2922
  38. data/examples/bts_aircraft/groupings.csv +0 -1
  39. data/examples/bts_aircraft/identities.csv +0 -1
  40. data/examples/bts_aircraft/negatives.csv +0 -1
  41. data/examples/bts_aircraft/normalizers.csv +0 -1
  42. data/examples/bts_aircraft/number_260.csv +0 -334
  43. data/examples/bts_aircraft/positives.csv +0 -1
  44. data/examples/bts_aircraft/test_bts_aircraft.rb +0 -116
  45. data/examples/first_name_matching.rb +0 -15
  46. data/examples/icao-bts.xls +0 -0
  47. data/lib/fuzzy_match/rule/normalizer.rb +0 -20
  48. data/lib/fuzzy_match/rule/stop_word.rb +0 -11
  49. data/lib/fuzzy_match/wrapper.rb +0 -73
  50. data/test/helper.rb +0 -12
  51. data/test/test_fuzzy_match.rb +0 -304
  52. data/test/test_fuzzy_match_convoluted.rb.disabled +0 -268
  53. data/test/test_grouping.rb +0 -28
  54. data/test/test_identity.rb +0 -34
  55. data/test/test_normalizer.rb +0 -10
@@ -0,0 +1,354 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe FuzzyMatch do
5
+ describe '#find' do
6
+ it %{finds the best match using string similarity} do
7
+ d = FuzzyMatch.new %w{ RATZ CATZ }
8
+ d.find('RITZ').should == 'RATZ'
9
+ end
10
+
11
+ it %{doesn't mind crazy characters} do
12
+ d = FuzzyMatch.new %w{ RATZ CATZ }
13
+ d.find('RíTZ').should == 'RATZ'
14
+ end
15
+
16
+ it %{not return any result if the maximum score is zero} do
17
+ FuzzyMatch.new(['a']).find('b').should be_nil
18
+ end
19
+
20
+ it %{finds exact matches} do
21
+ d = FuzzyMatch.new [ 'X' ]
22
+ d.find('X').should == 'X'
23
+ end
24
+ end
25
+
26
+ describe '#find_all' do
27
+ it %{return all records in sorted order} do
28
+ d = FuzzyMatch.new [ 'X', 'X22', 'Y', 'Y4' ], :groupings => [ /X/, /Y/ ], :must_match_grouping => true
29
+ d.find_all('X').should == ['X', 'X22' ]
30
+ d.find_all('A').should == []
31
+ end
32
+ end
33
+
34
+ describe '#find_best' do
35
+ it %{returns one or more records with the best score} do
36
+ d = FuzzyMatch.new [ 'X', 'X', 'X22', 'Y', 'Y', 'Y4' ], :groupings => [ /X/, /Y/ ], :must_match_grouping => true
37
+ d.find_best('X').should == ['X', 'X' ]
38
+ d.find_best('A').should == []
39
+ end
40
+ end
41
+
42
+ describe '#find_all_with_score' do
43
+ it %{return records with 2 scores} do
44
+ d = FuzzyMatch.new [ 'X', 'X22', 'Y', 'Y4' ], :groupings => [ /X/, /Y/ ], :must_match_grouping => true
45
+ d.find_all_with_score('X').should == [ ['X', 1, 1], ['X22', 0, 0.33333333333333337] ]
46
+ d.find_all_with_score('A').should == []
47
+ end
48
+ end
49
+
50
+ describe '#find_with_score' do
51
+ it %{return record with dice's and lev's scores} do
52
+ d = FuzzyMatch.new [ 'X', 'X22', 'Y', 'Y4' ], :groupings => [ /X/, /Y/ ], :must_match_grouping => true
53
+ d.find_with_score('X').should == ['X', 1, 1]
54
+ d.find_with_score('A').should be_nil
55
+ end
56
+ end
57
+
58
+ describe '#explain' do
59
+ before do
60
+ require 'stringio'
61
+ @capture = StringIO.new
62
+ @old_stdout = $stdout
63
+ $stdout = @capture
64
+ end
65
+ after do
66
+ $stdout = @old_stdout
67
+ end
68
+
69
+ it %{print a basic explanation to stdout} do
70
+ d = FuzzyMatch.new %w{ RATZ CATZ }
71
+ d.explain('RITZ')
72
+ @capture.rewind
73
+ @capture.read.should include('CATZ')
74
+ end
75
+
76
+ it %{explains match failures} do
77
+ FuzzyMatch.new(['aaa']).explain('bbb')
78
+ @capture.rewind
79
+ @capture.read.should =~ %r{No winner assigned.*aaa.*bbb}
80
+ end
81
+ end
82
+
83
+ describe "groupings replacings normalizers" do
84
+ it %{sometimes gets false results without them} do
85
+ d = FuzzyMatch.new ['BOEING 737-100/200', 'BOEING 737-900']
86
+ d.find('BOEING 737100 number 900').should == 'BOEING 737-900'
87
+ end
88
+
89
+ it %{can be used to improve results} do
90
+ d = FuzzyMatch.new ['BOEING 737-100/200', 'BOEING 737-900'], groupings: [ [/boeing/i, /7(\d\d)-?(\d\d\d)?/]]
91
+ d.find('BOEING 737100 number 900').should == 'BOEING 737-100/200'
92
+ end
93
+ end
94
+
95
+ describe "identities" do
96
+ it %{sometimes gets false results without them} do
97
+ # false positive without identity
98
+ d = FuzzyMatch.new %w{ foo bar }
99
+ d.find('baz').should == 'bar'
100
+ end
101
+
102
+ it %{can be used to improve results} do
103
+ d = FuzzyMatch.new %w{ foo bar }, :identities => [ /ba(.)/ ]
104
+ d.find('baz').should be_nil
105
+ end
106
+
107
+ it %{is sort of like backreferences} do
108
+ one = '1 sauk ONEONEONEONEONE'
109
+ two = '2 sauk TWOTWOTWOTWO'
110
+ d = FuzzyMatch.new([one, two])
111
+ d.find('1 sauk TWOTWOTWOTWO').should == two # wrong
112
+ d = FuzzyMatch.new([one, two], identities: [/\A(\d+)\s+(\w+)/])
113
+ d.find('1 sauk TWOTWOTWOTWO').should == one # correct
114
+ end
115
+ end
116
+
117
+ describe 'groupings' do
118
+ it %{sometimes gets false results without them} do
119
+ d = FuzzyMatch.new [ 'Barack Obama', 'George Bush' ]
120
+ d.find('Barack Bush').should == 'Barack Obama' # luke i am your father
121
+ d.find('George Obama').should == 'George Bush' # nooooooooooooooooooo
122
+ end
123
+
124
+ it %{can be used to improve results} do
125
+ d = FuzzyMatch.new [ 'Barack Obama', 'George Bush' ], :groupings => [ /Obama/, /Bush/ ]
126
+ d.find('Barack Bush').should == 'George Bush'
127
+ d.find('George Obama').should == 'Barack Obama'
128
+ end
129
+
130
+ it %{stays within the group} do
131
+ d = FuzzyMatch.new [ 'AB', 'CD' ]
132
+ d.find('ABCDCD').should == 'CD'
133
+ d = FuzzyMatch.new [ 'AB', 'CD' ], groupings: [/A/]
134
+ d.find('ABCDCD').should == 'AB'
135
+ end
136
+
137
+ describe 'with chains' do
138
+ describe 'hotel example' do
139
+ before do
140
+ @grandh = 'Grand Hyatt'
141
+ @h = 'Hyatt'
142
+ @hgarden = 'Hyatt Garden'
143
+ @grandhotel = 'Grand Hotel'
144
+ @fz = FuzzyMatch.new([@grandh, @h, @hgarden, @grandhotel], groupings: [ [ /hyatt/i, /garden/i, /grand/i ] ], stop_words: [ /hotel/i ])
145
+ end
146
+
147
+ it %{works as expected} do
148
+ @fz.find('Grand Hyatt').should == @grandh
149
+ @fz.find('Grand Hyatt Foobar').should == @grandh
150
+ @fz.find('Hyatt Garden').should == @hgarden
151
+ @fz.find('Hyatt Garden Foobar').should == @hgarden
152
+ end
153
+
154
+ it %{enforces some stuff} do
155
+ # nope
156
+ @fz.find('Grund Hyatt').should == @h
157
+ @fz.find('Grund Hyatt Foobar').should == @h
158
+ @fz.find('Hyatt Gurden').should == @h
159
+ @fz.find('Hyatt Gurden Foobar').should == @h
160
+ # hmm - hyatt misspelled, so totally prevented from matching hyatt
161
+ @fz.find('Grund Hyutt').should == @grandhotel
162
+ @fz.find('Grund Hyutt Foobar').should == @grandhotel
163
+ # precedence
164
+ @fz.find('Grand Hyatt Garden').should == @hgarden
165
+ @fz.find('Grand Hyatt Garden Foobar').should == @hgarden
166
+ # sanity
167
+ @fz.find('Grund Hyatt Garden').should == @hgarden
168
+ @fz.find('Grund Hyatt Garden Foobar').should == @hgarden
169
+ @fz.find('Grand Hyatt Gurden').should == @grandh
170
+ @fz.find('Grand Hyatt Gurden Foobar').should == @grandh
171
+ end
172
+
173
+ it %{is sticky} do
174
+ @fz.find('Grand Hotel').should == @grandhotel
175
+ @fz.find('Hotel Garden').should be_nil
176
+ @fz.find('Grand Hotel Garden').should == @grandhotel
177
+ end
178
+ end
179
+
180
+ it "helps with subgroups" do
181
+ d = FuzzyMatch.new [ 'Boeing 747', 'Boeing 747SR', 'Boeing ER6' ], :groupings => [ [/boeing/i, /(7\d{2})/] ]
182
+ d.find_all('Boeing 747').should == [ 'Boeing 747', 'Boeing 747SR' ]
183
+
184
+ d = FuzzyMatch.new [ 'Boeing 747', 'Boeing 747SR', 'Boeing ER6' ], :groupings => [ [/boeing/i, /(7\d{2})/] ]
185
+ d.find_all('Boeing ER6').should == ["Boeing ER6"]
186
+
187
+ d = FuzzyMatch.new [ 'Boeing 747', 'Boeing 747SR', 'Boeing ER6' ], :groupings => [ [/boeing/i, /(7|E\d{2})/i] ]
188
+ d.find_all('Boeing ER6').should == [ 'Boeing ER6' ]
189
+ d.find_all('Boeing 747').should == [ 'Boeing 747', 'Boeing 747SR' ]
190
+ end
191
+ end
192
+ end
193
+
194
+ describe "the :must_match_grouping option" do
195
+ it %{optionally only attempt matches with records that fit into a grouping} do
196
+ d = FuzzyMatch.new [ 'Barack Obama', 'George Bush' ], :groupings => [ /Obama/, /Bush/ ], :must_match_grouping => true
197
+ d.find('George Clinton').should be_nil
198
+
199
+ d = FuzzyMatch.new [ 'Barack Obama', 'George Bush' ], :groupings => [ /Obama/, /Bush/ ]
200
+ d.find('George Clinton', :must_match_grouping => true).should be_nil
201
+ end
202
+ end
203
+
204
+ describe "the :read option" do
205
+ it %{interpret a Numeric as an array index} do
206
+ ab = ['a', 'b']
207
+ ba = ['b', 'a']
208
+ haystack = [ab, ba]
209
+ by_first = FuzzyMatch.new haystack, :read => 0
210
+ by_last = FuzzyMatch.new haystack, :read => 1
211
+ by_first.find('a').should == ab
212
+ by_last.find('b').should == ab
213
+ by_first.find('b').should == ba
214
+ by_last.find('a').should == ba
215
+ end
216
+
217
+ it %{interpret a Symbol, etc. as hash key} do
218
+ ab = { :one => 'a', :two => 'b' }
219
+ ba = { :one => 'b', :two => 'a' }
220
+ haystack = [ab, ba]
221
+ by_first = FuzzyMatch.new haystack, :read => :one
222
+ by_last = FuzzyMatch.new haystack, :read => :two
223
+ by_first.find('a').should == ab
224
+ by_last.find('b').should == ab
225
+ by_first.find('b').should == ba
226
+ by_last.find('a').should == ba
227
+ end
228
+
229
+ MyStruct = Struct.new(:one, :two)
230
+ it %{interpret a Symbol as a method id (if the object responds to it)} do
231
+ ab = MyStruct.new('a', 'b')
232
+ ba = MyStruct.new('b', 'a')
233
+ haystack = [ab, ba]
234
+ by_first = FuzzyMatch.new haystack, :read => :one
235
+ by_last = FuzzyMatch.new haystack, :read => :two
236
+ by_first.read.should == :one
237
+ by_last.read.should == :two
238
+ by_first.find('a').should == ab
239
+ by_last.find('b').should == ab
240
+ by_first.find('b').should == ba
241
+ by_last.find('a').should == ba
242
+ end
243
+ end
244
+
245
+ describe 'the :must_match_at_least_one_word option' do
246
+ it %{optionally require that the matching record share at least one word with the needle} do
247
+ d = FuzzyMatch.new %w{ RATZ CATZ }, :must_match_at_least_one_word => true
248
+ d.find('RITZ').should be_nil
249
+
250
+ d = FuzzyMatch.new ["Foo's Bar"], :must_match_at_least_one_word => true
251
+ d.find("Foo's").should == "Foo's Bar"
252
+ d.find("'s").should be_nil
253
+ d.find("Foo").should be_nil
254
+
255
+ d = FuzzyMatch.new ["Bolivia, Plurinational State of"], :must_match_at_least_one_word => true
256
+ d.find("Bolivia").should == "Bolivia, Plurinational State of"
257
+ end
258
+
259
+ it %{use STOP WORDS} do
260
+ d = FuzzyMatch.new [ 'A HOTEL', 'B HTL' ]
261
+ d.find('A HTL', :must_match_at_least_one_word => true).should == 'B HTL'
262
+
263
+ d = FuzzyMatch.new [ 'A HOTEL', 'B HTL' ], :must_match_at_least_one_word => true
264
+ d.find('A HTL').should == 'B HTL'
265
+
266
+ d = FuzzyMatch.new [ 'A HOTEL', 'B HTL' ], :must_match_at_least_one_word => true, :stop_words => [ %r{HO?TE?L} ]
267
+ d.find('A HTL').should == 'A HOTEL'
268
+ end
269
+
270
+ it %{not be fooled by substrings (but rather compare whole words to whole words)} do
271
+ d = FuzzyMatch.new [ 'PENINSULA HOTELS' ], :must_match_at_least_one_word => true
272
+ d.find('DOLCE LA HULPE BXL FI').should be_nil
273
+ end
274
+
275
+ it %{not be case-sensitive when checking for sharing of words} do
276
+ d = FuzzyMatch.new [ 'A', 'B' ]
277
+ d.find('a', :must_match_at_least_one_word => true).should == 'A'
278
+ end
279
+ end
280
+
281
+ describe "the :gather_last_result option" do
282
+ it %{not gather metadata about the last result by default} do
283
+ d = FuzzyMatch.new %w{ NISSAN HONDA }
284
+ d.find('MISSAM')
285
+ lambda do
286
+ d.last_result
287
+ end.should raise_error(::RuntimeError, /gather_last_result/)
288
+ end
289
+
290
+ it %{optionally gather metadata about the last result} do
291
+ d = FuzzyMatch.new %w{ NISSAN HONDA }
292
+ d.find 'MISSAM', :gather_last_result => true
293
+ d.last_result.score.should == 0.6
294
+ d.last_result.winner.should == 'NISSAN'
295
+ end
296
+ end
297
+
298
+ describe 'quirks' do
299
+ it %{should not return false negatives because of one-letter similarities} do
300
+ # dices coefficient doesn't think these two are similar at all because it looks at pairs
301
+ FuzzyMatch.score_class.new('X foo', 'X bar').dices_coefficient_similar.should == 0
302
+ # so we must compensate for that somewhere
303
+ d = FuzzyMatch.new ['X foo', 'randomness']
304
+ d.find('X bar').should == 'X foo'
305
+ # without making false positives
306
+ d.find('Y bar').should be_nil
307
+ end
308
+
309
+ it %{finds possible matches even when pair distance fails} do
310
+ d = FuzzyMatch.new ['XX', '2 A']
311
+ d.find('2A').should == '2 A'
312
+ d = FuzzyMatch.new ['XX', '2A']
313
+ d.find('2 A').should == '2A'
314
+ end
315
+
316
+ it %{weird blow ups} do
317
+ d = FuzzyMatch.new ['XX', '2 A']
318
+ d.find('A').should == '2 A'
319
+ d = FuzzyMatch.new ['XX', 'A']
320
+ d.find('2 A').should == 'A'
321
+ end
322
+
323
+ it %{from the wild 1} do
324
+ d = FuzzyMatch.new ["Doyle Collection", "Trump Collection", "Luxury Collection", "Autograph Collection"]
325
+ d.find("Algonquin Autograph Collection").should == "Autograph Collection"
326
+ end
327
+
328
+ end
329
+
330
+ describe 'deprecations' do
331
+ it %{takes :must_match_blocking as :must_match_grouping} do
332
+ d = FuzzyMatch.new [], :must_match_blocking => :a
333
+ d.default_options[:must_match_grouping].should == :a
334
+ end
335
+
336
+ it %{takes :haystack_reader as :read} do
337
+ d = FuzzyMatch.new [], :haystack_reader => :c
338
+ d.read.should == :c
339
+ end
340
+
341
+ it %{takes :blockings as :groupings} do
342
+ d = FuzzyMatch.new [], :blockings => [ /X/, /Y/ ]
343
+ d.groupings.should == [ FuzzyMatch::Rule::Grouping.new(/X/), FuzzyMatch::Rule::Grouping.new(/Y/) ]
344
+ end
345
+ end
346
+
347
+ it %{defaults to a pure-ruby engine, but also has amatch} do
348
+ if defined?($testing_amatch) and $testing_amatch
349
+ FuzzyMatch.engine.should == :amatch
350
+ else
351
+ FuzzyMatch.engine.should == :pure_ruby
352
+ end
353
+ end
354
+ end
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+
3
+ describe FuzzyMatch::Rule::Grouping do
4
+ it %{matches a single string argument} do
5
+ b = FuzzyMatch::Rule::Grouping.new %r{apple}
6
+ b.xmatch?(r('2 apples')).should == true
7
+ end
8
+
9
+ it %{embraces case insensitivity} do
10
+ b = FuzzyMatch::Rule::Grouping.new %r{apple}i
11
+ b.xmatch?(r('2 Apples')).should == true
12
+ end
13
+
14
+ it %{xjoins two string arguments} do
15
+ b = FuzzyMatch::Rule::Grouping.new %r{apple}
16
+ b.xjoin?(r('apple'), r('2 apples')).should == true
17
+ end
18
+
19
+ it %{fails to xjoin two string arguments} do
20
+ b = FuzzyMatch::Rule::Grouping.new %r{apple}
21
+ b.xjoin?(r('orange'), r('2 apples')).should == false
22
+ end
23
+
24
+ it %{returns nil instead of false when it has no information} do
25
+ b = FuzzyMatch::Rule::Grouping.new %r{apple}
26
+ b.xjoin?(r('orange'), r('orange')).should be_nil
27
+ end
28
+
29
+ it %{has chains} do
30
+ h, gr, ga = FuzzyMatch::Rule::Grouping.make([/hyatt/, /grand/, /garden/])
31
+ h.xjoin?(r('hyatt'), r('hyatt')).should == true
32
+
33
+ h.xjoin?(r('grund hyatt'), r('grand hyatt')).should == true
34
+ gr.xjoin?(r('grund hyatt'), r('grand hyatt')).should == false
35
+ ga.xjoin?(r('grund hyatt'), r('grand hyatt')).should be_nil
36
+
37
+ h.xjoin?(r('hyatt gurden'), r('hyatt garden')).should == true
38
+ gr.xjoin?(r('hyatt gurden'), r('hyatt garden')).should be_nil
39
+ ga.xjoin?(r('hyatt gurden'), r('hyatt garden')).should == false
40
+
41
+ h.xjoin?(r('grand hyatt'), r('grand hyatt')).should == false # sacrificing itself
42
+ gr.xjoin?(r('grand hyatt'), r('grand hyatt')).should == true
43
+ ga.xjoin?(r('grand hyatt'), r('grand hyatt')).should be_nil
44
+
45
+ h.xjoin?(r('hyatt garden'), r('hyatt garden')).should == false # sacrificing itself
46
+ gr.xjoin?(r('hyatt garden'), r('hyatt garden')).should be_nil
47
+ ga.xjoin?(r('hyatt garden'), r('hyatt garden')).should == true
48
+
49
+ h.xjoin?(r('grand hyatt garden'), r('grand hyatt garden')).should == false # sacrificing itself
50
+ gr.xjoin?(r('grand hyatt garden'), r('grand hyatt garden')).should == true
51
+ ga.xjoin?(r('grand hyatt garden'), r('grand hyatt garden')).should == true # NOT sacrificing itself?
52
+ end
53
+
54
+ private
55
+
56
+ def r(str)
57
+ FuzzyMatch::Record.new str
58
+ end
59
+
60
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe FuzzyMatch::Rule::Identity do
4
+ it %{determines whether two records COULD be identical} do
5
+ i = FuzzyMatch::Rule::Identity.new %r{(A)[ ]*(\d)}
6
+ i.identical?(r('A1'), r('A 1foobar')).should == true
7
+ end
8
+
9
+ it %{determines that two records MUST NOT be identical} do
10
+ i = FuzzyMatch::Rule::Identity.new %r{(A)[ ]*(\d)}
11
+ i.identical?(r('A1'), r('A 2foobar')).should == false
12
+ end
13
+
14
+ it %{returns nil indicating no information} do
15
+ i = FuzzyMatch::Rule::Identity.new %r{(A)[ ]*(\d)}
16
+ i.identical?(r('B1'), r('A 2foobar')).should == nil
17
+ end
18
+
19
+ it %{embraces case insensitivity} do
20
+ i = FuzzyMatch::Rule::Identity.new %r{(A)[ ]*(\d)}i
21
+ i.identical?(r('A1'), r('a 1foobar')).should == true
22
+ end
23
+
24
+ private
25
+
26
+ def r(str)
27
+ FuzzyMatch::Record.new str
28
+ end
29
+ end
@@ -1,6 +1,6 @@
1
- require 'helper'
1
+ require 'spec_helper'
2
2
 
3
- describe FuzzyMatch::Wrapper do
3
+ describe FuzzyMatch::Record do
4
4
  it %{does not treat "'s" as a word} do
5
5
  assert_split ["foo's", "bar"], "Foo's Bar"
6
6
  end
@@ -20,10 +20,6 @@ describe FuzzyMatch::Wrapper do
20
20
  private
21
21
 
22
22
  def assert_split(ary, str)
23
- FuzzyMatch::Wrapper.new(null_fuzzy_match, str, true).words.must_equal ary
24
- end
25
-
26
- def null_fuzzy_match
27
- FuzzyMatch.new []
23
+ FuzzyMatch::Record.new(str).words.should == ary
28
24
  end
29
25
  end
@@ -0,0 +1,21 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ RSpec.configure do |config|
8
+ config.treat_symbols_as_metadata_keys_with_true_values = true
9
+ config.run_all_when_everything_filtered = true
10
+ config.filter_run :focus
11
+
12
+ # Run specs in random order to surface order dependencies. If you find an
13
+ # order dependency and want to debug it, you can fix the order by providing
14
+ # the seed, which is printed after each run.
15
+ # --seed 1234
16
+ config.order = 'random'
17
+ end
18
+
19
+ require 'pry'
20
+
21
+ require 'fuzzy_match'