scope_by_fuzzy 0.0.2
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/LICENSE +20 -0
- data/README.rdoc +44 -0
- data/init.rb +1 -0
- data/lib/generators/scope_by_fuzzy_install/USAGE +3 -0
- data/lib/generators/scope_by_fuzzy_install/scope_by_fuzzy_install_generator.rb +18 -0
- data/lib/generators/scope_by_fuzzy_install/templates/migration.rb +42 -0
- data/lib/scope_by_fuzzy.rb +12 -0
- data/lib/scope_by_fuzzy/named_scope.rb +46 -0
- data/spec/scope_by_fuzzy_spec.rb +7 -0
- data/spec/spec_helper.rb +9 -0
- metadata +78 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Alejandro Juarez
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
= Description
|
2
|
+
|
3
|
+
The scope_by_soundex gem provides a simple interface to use the set of functions of contrib/fuzzystringmatching for PostgreSQL.
|
4
|
+
|
5
|
+
== How to install It
|
6
|
+
|
7
|
+
Edit your Gemfile and insert the next line:
|
8
|
+
|
9
|
+
gem "scope_by_soundex"
|
10
|
+
|
11
|
+
Then use the bundler to install It:
|
12
|
+
|
13
|
+
$ bundle install
|
14
|
+
|
15
|
+
Then execute the rails migration generator:
|
16
|
+
|
17
|
+
$ ./script/rails generate scope_by_soundex_install
|
18
|
+
|
19
|
+
And finally run the rails migrations to add the functions for PostgreSQL:
|
20
|
+
|
21
|
+
$ rake db:migrate
|
22
|
+
|
23
|
+
== How to use It
|
24
|
+
|
25
|
+
# scope_by_soundex_matcher
|
26
|
+
|
27
|
+
class Person < ActiveRecord::Base
|
28
|
+
scope_by_soundex_matcher :find_by_fullname, :fields => [:firstname, :lastname]
|
29
|
+
end
|
30
|
+
|
31
|
+
Person.find_by_fullname 'Alejandro' => Returns a collection of active_record objects
|
32
|
+
|
33
|
+
|
34
|
+
# scope_by_difference_matcher
|
35
|
+
|
36
|
+
class Person < ActiveRecord::Base
|
37
|
+
scope_by_difference_matcher :find_by_fullname, :fields => [:firstname, :lastname]
|
38
|
+
end
|
39
|
+
|
40
|
+
Person.find_by_fullname 'Alejandro' => Returns a collection of active_record objects
|
41
|
+
|
42
|
+
== Copyright
|
43
|
+
|
44
|
+
Copyright (c) 2010 Alejandro Juarez. See LICENSE for details.
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'scope_by_fuzzy'
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rails/generators/migration'
|
2
|
+
class ScopeByFuzzyInstallGenerator < Rails::Generators::Base
|
3
|
+
include Rails::Generators::Migration
|
4
|
+
|
5
|
+
desc "Generates a migration file to add Fuzzy String Matching functions to your PostgreSQL database."
|
6
|
+
|
7
|
+
def self.source_root
|
8
|
+
@_source_root = File.expand_path('../templates', __FILE__)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.next_migration_number(path)
|
12
|
+
Time.now.utc.strftime("%Y%m%d%H%M%S")
|
13
|
+
end
|
14
|
+
|
15
|
+
def copy_migration_template
|
16
|
+
migration_template "migration.rb", "db/migrate/add_scope_by_fuzzy"
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class AddScopeByFuzzy < ActiveRecord::Migration
|
2
|
+
|
3
|
+
def self.up
|
4
|
+
execute "SET search_path = public;"
|
5
|
+
|
6
|
+
execute "CREATE OR REPLACE FUNCTION levenshtein (text,text) RETURNS int AS '$libdir/fuzzystrmatch','levenshtein' LANGUAGE C IMMUTABLE STRICT;"
|
7
|
+
|
8
|
+
execute "CREATE OR REPLACE FUNCTION levenshtein (text,text,int,int,int) RETURNS int AS '$libdir/fuzzystrmatch','levenshtein_with_costs' LANGUAGE C IMMUTABLE STRICT;"
|
9
|
+
|
10
|
+
execute "CREATE OR REPLACE FUNCTION metaphone (text,int) RETURNS text AS '$libdir/fuzzystrmatch','metaphone'LANGUAGE C IMMUTABLE STRICT;"
|
11
|
+
|
12
|
+
execute "CREATE OR REPLACE FUNCTION soundex(text) RETURNS text AS '$libdir/fuzzystrmatch', 'soundex' LANGUAGE C IMMUTABLE STRICT;"
|
13
|
+
|
14
|
+
execute "CREATE OR REPLACE FUNCTION text_soundex(text) RETURNS text AS '$libdir/fuzzystrmatch', 'soundex' LANGUAGE C IMMUTABLE STRICT;"
|
15
|
+
|
16
|
+
execute "CREATE OR REPLACE FUNCTION difference(text,text) RETURNS int AS '$libdir/fuzzystrmatch', 'difference' LANGUAGE C IMMUTABLE STRICT;"
|
17
|
+
|
18
|
+
execute "CREATE OR REPLACE FUNCTION dmetaphone (text) RETURNS text AS '$libdir/fuzzystrmatch', 'dmetaphone' LANGUAGE C IMMUTABLE STRICT;"
|
19
|
+
|
20
|
+
execute "CREATE OR REPLACE FUNCTION dmetaphone_alt (text) RETURNS text AS '$libdir/fuzzystrmatch', 'dmetaphone_alt' LANGUAGE C IMMUTABLE STRICT;"
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.down
|
24
|
+
execute "SET search_path = public;"
|
25
|
+
|
26
|
+
execute "DROP FUNCTION dmetaphone_alt (text);"
|
27
|
+
|
28
|
+
execute "DROP FUNCTION dmetaphone (text);"
|
29
|
+
|
30
|
+
execute "DROP FUNCTION difference(text,text);"
|
31
|
+
|
32
|
+
execute "DROP FUNCTION text_soundex(text);"
|
33
|
+
|
34
|
+
execute "DROP FUNCTION soundex(text);"
|
35
|
+
|
36
|
+
execute "DROP FUNCTION metaphone (text,int);"
|
37
|
+
|
38
|
+
execute "DROP FUNCTION levenshtein (text,text,int,int,int);"
|
39
|
+
|
40
|
+
execute "DROP FUNCTION levenshtein (text,text);"
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module ScopeByFuzzy
|
2
|
+
def enable_activerecord
|
3
|
+
return if ActiveRecord::Base.respond_to? :scope_by_soundex_matcher and ActiveRecord::Base.respond_to? :scope_by_difference_matcher
|
4
|
+
require 'scope_by_fuzzy/named_scope'
|
5
|
+
::ActiveRecord::Base.send :include, ScopeByFuzzy::NamedScope
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
if defined? Rails
|
10
|
+
include ScopeByFuzzy
|
11
|
+
ScopeByFuzzy.enable_activerecord if defined? ActiveRecord
|
12
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module ScopeByFuzzy
|
2
|
+
module NamedScope
|
3
|
+
def self.included(base)
|
4
|
+
base.extend ClassMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
|
9
|
+
# scope_by_soundex
|
10
|
+
#
|
11
|
+
# Example:
|
12
|
+
# class Person < ActiveRecord::Base
|
13
|
+
# scope_by_soundex find_by_fullname, :fields => [:firstname, :lastname]
|
14
|
+
# end
|
15
|
+
# Person.find_by_fullname 'Alejandro'
|
16
|
+
def scope_by_soundex(method_name, options={})
|
17
|
+
sql = options[:fields].collect { |field| "soundex(#{field}) = soundex(:q)"}.join(' OR ')
|
18
|
+
scope method_name.to_sym, lambda {|string| where(sql, :q => string) }
|
19
|
+
end
|
20
|
+
|
21
|
+
# scope_by_difference
|
22
|
+
#
|
23
|
+
# Example:
|
24
|
+
# class Person < ActiveRecord::Base
|
25
|
+
# scope_by_difference find_by_fullname, :fields => [:firstname, :lastname]
|
26
|
+
# OR
|
27
|
+
# scope_by_difference find_by_fullname, :fields => [:firstname, :lastname], :position => 4, :operator => '>'
|
28
|
+
# OR
|
29
|
+
# scope_by_difference find_by_fullname, :by_sql => 'difference(firstname, :q) > 3 OR difference(:lastname, :q) > 4"
|
30
|
+
# end
|
31
|
+
# Person.find_by_fullname 'Alejandro'
|
32
|
+
def scope_by_difference(method_name, options={})
|
33
|
+
unless options.has_key? :by_sql
|
34
|
+
options[:position] ||= 3
|
35
|
+
options[:operator] = '>'
|
36
|
+
sql = options[:fields].collect { |field|"difference(#{field}, :q) #{options[:operator]} #{options[:position]}" }.join(' OR ')
|
37
|
+
else
|
38
|
+
sql = options[:by_sql]
|
39
|
+
end
|
40
|
+
scope method_name.to_sym, lambda {|string| where(sql, :q => string) }
|
41
|
+
end
|
42
|
+
|
43
|
+
# TODO: The following PostgreSQL functions are not implemented: dmetaphone_alt, dmetaphone, text_soundex, metaphone and levenshtein.
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: scope_by_fuzzy
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Alejandro Juarez
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-10-01 00:00:00 -05:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: The scope_by_fuzzy gem uses the set of functions of contrib/fuzzystringmatching for PostgreSQL.
|
23
|
+
email: alex@monsterlabs.com.mx
|
24
|
+
executables: []
|
25
|
+
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files:
|
29
|
+
- LICENSE
|
30
|
+
- README.rdoc
|
31
|
+
files:
|
32
|
+
- LICENSE
|
33
|
+
- init.rb
|
34
|
+
- lib/generators/scope_by_fuzzy_install/USAGE
|
35
|
+
- lib/generators/scope_by_fuzzy_install/scope_by_fuzzy_install_generator.rb
|
36
|
+
- lib/generators/scope_by_fuzzy_install/templates/migration.rb
|
37
|
+
- lib/scope_by_fuzzy.rb
|
38
|
+
- lib/scope_by_fuzzy/named_scope.rb
|
39
|
+
- README.rdoc
|
40
|
+
- spec/scope_by_fuzzy_spec.rb
|
41
|
+
- spec/spec_helper.rb
|
42
|
+
has_rdoc: true
|
43
|
+
homepage: http://github.com/monsterlabs/scope_by_fuzzy
|
44
|
+
licenses: []
|
45
|
+
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options:
|
48
|
+
- --charset=UTF-8
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
hash: 3
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
version: "0"
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
hash: 3
|
66
|
+
segments:
|
67
|
+
- 0
|
68
|
+
version: "0"
|
69
|
+
requirements: []
|
70
|
+
|
71
|
+
rubyforge_project:
|
72
|
+
rubygems_version: 1.3.7
|
73
|
+
signing_key:
|
74
|
+
specification_version: 3
|
75
|
+
summary: This gem provides the soundex and difference postgresql functions to determine similarities and distance between strings
|
76
|
+
test_files:
|
77
|
+
- spec/scope_by_fuzzy_spec.rb
|
78
|
+
- spec/spec_helper.rb
|