Skip to content
This repository has been archived by the owner on Sep 27, 2022. It is now read-only.

Commit

Permalink
Adds Rails 4 compatibility. Fixes #12.
Browse files Browse the repository at this point in the history
  • Loading branch information
mezis committed Aug 31, 2013
1 parent 27085dd commit 5350689
Show file tree
Hide file tree
Showing 10 changed files with 247 additions and 62 deletions.
6 changes: 4 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,16 @@ gemfile:
- gemfiles/rails32.gemfile
- gemfiles/rails32_pg.gemfile
- gemfiles/rails32_mysql.gemfile
- gemfiles/rails40.gemfile
before_install: bundle install
bundler_args:
matrix:
exclude:
- rvm: 2.0.0
gemfile: gemfiles/rails23.gemfile
env: TRAVIS=TRUE
before_script:
- psql -c 'create database fuzzily_test;' -U postgres
- mysql -e 'create database fuzzily_test;'
env: TRAVIS=TRUE
env:
global:
- TRAVIS=TRUE
4 changes: 4 additions & 0 deletions Appraisals
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,7 @@ end
appraise "rails32-mysql" do
gem "activerecord", "~> 3.2.0"
end

appraise "rails40" do
gem "activerecord", "~> 4.0.0"
end
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ PATH
activerecord (>= 2.3.17)

GEM
remote: http://yarp.dev/
remote: https://rubygems.org/
specs:
activemodel (3.2.14)
activesupport (= 3.2.14)
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Blurrily finds misspelled, prefix, or partial needles in a haystack of
strings. It's a fast, [trigram](http://en.wikipedia.org/wiki/N-gram)-based, database-backed [fuzzy](http://en.wikipedia.org/wiki/Approximate_string_matching) string search/match engine for Rails.
Loosely inspired from an [old blog post](http://unirec.blogspot.co.uk/2007/12/live-fuzzy-search-using-n-grams-in.html).

Tested with ActiveRecord (2.3, 3.0, 3.1, 3.2) on various Rubies (1.8.7, 1.9.2, 1.9.3, 2.0.0) and the most common adapters (SQLite3, MySQL, and PostgreSQL).
Tested with ActiveRecord (2.3, 3.0, 3.1, 3.2, 4.0) on various Rubies (1.8.7, 1.9.2, 1.9.3, 2.0.0) and the most common adapters (SQLite3, MySQL, and PostgreSQL).

If your dateset is big, if you need yet more speed, or do not use ActiveRecord,
check out [blurrily](http://github.com/mezis/blurrily), another gem (backed with a C extension)
Expand Down Expand Up @@ -71,7 +71,9 @@ Search!
MyStuff.find_by_fuzzy_name('Some Name', :limit => 10)
# => records

You can force an update on a specific record with

MyStuff.find(123).update_fuzzy_name!

## Indexing more than one field

Expand Down
2 changes: 1 addition & 1 deletion gemfiles/rails32.gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ PATH
activerecord (>= 2.3.17)

GEM
remote: http://yarp.dev/
remote: https://rubygems.org/
specs:
activemodel (3.2.14)
activesupport (= 3.2.14)
Expand Down
7 changes: 7 additions & 0 deletions gemfiles/rails40.gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# This file was generated by Appraisal

source "https://rubygems.org"

gem "activerecord", "~> 4.0.0"

gemspec :path=>"../"
89 changes: 89 additions & 0 deletions gemfiles/rails40.gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
PATH
remote: /Users/mezis/Dropbox/Development/fuzzily
specs:
fuzzily (0.2.4)
activerecord (>= 2.3.17)

GEM
remote: https://rubygems.org/
specs:
activemodel (4.0.0)
activesupport (= 4.0.0)
builder (~> 3.1.0)
activerecord (4.0.0)
activemodel (= 4.0.0)
activerecord-deprecated_finders (~> 1.0.2)
activesupport (= 4.0.0)
arel (~> 4.0.0)
activerecord-deprecated_finders (1.0.3)
activesupport (4.0.0)
i18n (~> 0.6, >= 0.6.4)
minitest (~> 4.2)
multi_json (~> 1.3)
thread_safe (~> 0.1)
tzinfo (~> 0.3.37)
appraisal (0.5.2)
bundler
rake
arel (4.0.0)
atomic (1.1.13)
builder (3.1.4)
coderay (1.0.9)
colorize (0.5.8)
coveralls (0.6.7)
colorize
multi_json (~> 1.3)
rest-client
simplecov (>= 0.7)
thor
diff-lcs (1.2.4)
i18n (0.6.5)
method_source (0.8.2)
mime-types (1.25)
minitest (4.7.5)
multi_json (1.7.9)
mysql2 (0.3.13)
pg (0.16.0)
pry (0.9.12.2)
coderay (~> 1.0.5)
method_source (~> 0.8)
slop (~> 3.4)
pry-nav (0.2.3)
pry (~> 0.9.10)
rake (10.1.0)
rest-client (1.6.7)
mime-types (>= 1.16)
rspec (2.14.1)
rspec-core (~> 2.14.0)
rspec-expectations (~> 2.14.0)
rspec-mocks (~> 2.14.0)
rspec-core (2.14.5)
rspec-expectations (2.14.2)
diff-lcs (>= 1.1.3, < 2.0)
rspec-mocks (2.14.3)
simplecov (0.7.1)
multi_json (~> 1.0)
simplecov-html (~> 0.7.1)
simplecov-html (0.7.1)
slop (3.4.6)
sqlite3 (1.3.8)
thor (0.18.1)
thread_safe (0.1.2)
atomic
tzinfo (0.3.37)

PLATFORMS
ruby

DEPENDENCIES
activerecord (~> 4.0.0)
appraisal
coveralls
fuzzily!
mysql2
pg
pry
pry-nav
rake
rspec
sqlite3
75 changes: 54 additions & 21 deletions lib/fuzzily/model.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ module Model

def self.included(by)
by.ancestors.include?(ActiveRecord::Base) or raise 'Not included in an ActiveRecord subclass'

scope_method = ActiveRecord::VERSION::MAJOR == 2 ? :named_scope : :scope
by.extend(ClassMethods)

by.class_eval do
return if class_variable_defined?(:@@fuzzily_trigram_model)
Expand All @@ -18,31 +17,65 @@ def self.included(by)
validates_presence_of :score
validates_presence_of :fuzzy_field

send scope_method, :for_model, lambda { |model| {
:conditions => { :owner_type => model.kind_of?(Class) ? model.name : model }
}}
send scope_method, :for_field, lambda { |field_name| {
:conditions => { :fuzzy_field => field_name }
}}
send scope_method, :with_trigram, lambda { |trigrams| {
:conditions => { :trigram => trigrams }
}}

_add_fuzzy_scopes
class_variable_set(:@@fuzzily_trigram_model, true)
end

by.extend(ClassMethods)
end

module ClassMethods
def matches_for(text)
trigrams = Fuzzily::String.new(text).trigrams
self.
scoped(:select => 'owner_id, owner_type, count(*) AS matches, MAX(score) AS score').
scoped(:group => 'owner_id, owner_type').
scoped(:order => 'matches DESC, score ASC').
with_trigram(trigrams).
map(&:owner)
_matches_for_trigrams Fuzzily::String.new(text).trigrams
end

private

module Rails2
def _matches_for_trigrams(trigrams)
self.
scoped(:select => 'owner_id, owner_type, count(*) AS matches, MAX(score) AS score').
scoped(:group => 'owner_id, owner_type').
scoped(:order => 'matches DESC, score ASC').
with_trigram(trigrams).
map(&:owner)
end

def _add_fuzzy_scopes
named_scope :for_model, lambda { |model| {
:conditions => { :owner_type => model.kind_of?(Class) ? model.name : model }
}}
named_scope :for_field, lambda { |field_name| {
:conditions => { :fuzzy_field => field_name }
}}
named_scope :with_trigram, lambda { |trigrams| {
:conditions => { :trigram => trigrams }
}}
named_scope :limit, lambda { |count| { :limit => count }}
end
end

module Rails3
def _matches_for_trigrams(trigrams)
self.
select('owner_id, owner_type, count(*) AS matches, MAX(score) AS score').
group('owner_id, owner_type').
order('matches DESC, score ASC').
with_trigram(trigrams).
map(&:owner)
end

def _add_fuzzy_scopes
scope :for_model, lambda { |model|
where(:owner_type => model.kind_of?(Class) ? model.name : model)
}
scope :for_field, lambda { |field_name| where(:fuzzy_field => field_name) }
scope :with_trigram, lambda { |trigrams| where(:trigram => trigrams) }
end
end

if ActiveRecord::VERSION::MAJOR == 2
include Rails2
else
include Rails3
end
end
end
Expand Down
Loading

0 comments on commit 5350689

Please sign in to comment.