From 4ccbab826c30632e0549089ca1eea2e8ad8a9ca1 Mon Sep 17 00:00:00 2001 From: Ben Hadley-Evans Date: Tue, 25 Aug 2015 14:29:12 +0100 Subject: [PATCH] Do not raise on missing objects. The use of ActiveRecord's #find meant missing IDs raised AR::RecordNotFound. This might come up if an object was created and then deleted without its trigram data also being deleted. To avoid the exception this uses #where instead of #find which will ignore missing results. Due to the method with which the records are sorted to match the trigram query, in these cases nils were cropping up in the results, so this uses #compact to just return the records. The first test case ensures no exceptions are raised. The second test case ensures the fuzzy find still works and that no nils are returned. --- lib/fuzzily/searchable.rb | 6 +++--- spec/fuzzily/searchable_spec.rb | 18 ++++++++++++++++-- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/lib/fuzzily/searchable.rb b/lib/fuzzily/searchable.rb index f8f4ab7..7f920f0 100644 --- a/lib/fuzzily/searchable.rb +++ b/lib/fuzzily/searchable.rb @@ -51,12 +51,12 @@ def _find_by_fuzzy(_o, pattern, options={}) matches_for(pattern) records = _load_for_ids(trigrams.map(&:owner_id)) # order records as per trigram query (no portable way to do this in SQL) - trigrams.map { |t| records[t.owner_id] } + trigrams.map { |t| records[t.owner_id] }.compact end def _load_for_ids(ids) {}.tap do |result| - find(ids).each { |_r| result[_r.id] = _r } + where(:id => ids).each { |_r| result[_r.id] = _r } end end @@ -136,7 +136,7 @@ def make_field_fuzzily_searchable(field, options={}) after_save do |record| next unless record.send("#{field}_changed?".to_sym) - + record.send(_o.update_trigrams_method) end diff --git a/spec/fuzzily/searchable_spec.rb b/spec/fuzzily/searchable_spec.rb index 9c25fe0..aa0fb94 100644 --- a/spec/fuzzily/searchable_spec.rb +++ b/spec/fuzzily/searchable_spec.rb @@ -12,7 +12,7 @@ before(:each) { prepare_trigrams_table } before(:each) { prepare_owners_table } - subject do + subject do silence_warnings do Stuff = Class.new(ActiveRecord::Base) end @@ -73,7 +73,7 @@ def Stuff.name ; 'Stuff' ; end before do subject.fuzzily_searchable :name end - + it 're-creates trigrams' do subject.create!(:name => 'Paris') old_ids = Trigram.all.map(&:id) @@ -171,6 +171,20 @@ def Stuff.name ; 'Stuff' ; end 3.times { subject.create!(:name => 'Paris') } subject.find_by_fuzzy_name('Paris', :offset => 2).length.should == 1 end + + it 'does not raise on missing objects' do + subject.fuzzily_searchable :name + belgium = subject.create(:name => 'Belgium') + belgium.delete + subject.find_by_fuzzy_name('Belgium') + end + + it 'finds others alongside missing' do + subject.fuzzily_searchable :name + belgium1, belgium2 = 2.times.map { subject.create(:name => 'Belgium') } + belgium1.delete + subject.find_by_fuzzy_name('Belgium').should == [belgium2] + end end end