Chrononaut-no_fuzz 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.
data/CHANGELOG ADDED
@@ -0,0 +1 @@
1
+ v0.0.1 Test release
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 [name of plugin creator]
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/Manifest ADDED
@@ -0,0 +1,21 @@
1
+ Rakefile
2
+ README.markdown
3
+ tasks/no_fuzz_tasks.rake
4
+ uninstall.rb
5
+ init.rb
6
+ generators/no_fuzz/no_fuzz_generator.rb
7
+ generators/no_fuzz/templates/model.rb
8
+ generators/no_fuzz/templates/migration.rb
9
+ generators/no_fuzz/USAGE
10
+ rails/init.rb
11
+ CHANGELOG
12
+ lib/no_fuzz.rb
13
+ MIT-LICENSE
14
+ no_fuzz.gemspec
15
+ install.rb
16
+ test/no_fuzz_test.rb
17
+ test/test_helper.rb
18
+ test/database.yml
19
+ test/schema.rb
20
+ test/test.sqlite3
21
+ Manifest
data/README.markdown ADDED
@@ -0,0 +1,34 @@
1
+ # NoFuzz
2
+
3
+ Simple as can be fuzzy search. Works with any database supported by Active
4
+ Record. No dependencies.
5
+
6
+ Based on code and ideas in Steven Ruttenberg's nice blog entry "Live fuzzy
7
+ search using n-grams in Rails" [1].
8
+
9
+ Note that this family of fuzzy search techniques work best on dictionary-type
10
+ lookups, i.e not for large amounts of text.
11
+
12
+ kristian's acts_as_fuzzy_search [2] is a similar plugin, but it targets DataMapper.
13
+
14
+ 1: http://unirec.blogspot.com/2007/12/live-fuzzy-search-using-n-grams-in.html
15
+
16
+ 2: http://github.com/mkristian/kristians_rails_plugins/tree/master/act_as_fuzzy_search
17
+
18
+ # Basic Usage
19
+
20
+ Add the following code in the model you'd like to index:
21
+
22
+ include NoFuzz
23
+ fuzzy :field
24
+
25
+ Where field is the field used for the indexing data (you can use multiple fields
26
+ if you want).
27
+
28
+ Populate the index by running 'Model.populate_trigram_index'. Then, you can
29
+ search fuzzily with the fuzzy_find method:
30
+
31
+ Model.fuzzy_find("query")
32
+ Model.fuzzy_find("query", 10) # find maximum 10 rows
33
+
34
+ Copyright (c) 2009 Bjørn Arild Mæland, released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,37 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'rubygems'
3
+ require 'rake'
4
+ require 'rake/testtask'
5
+ require 'rake/rdoctask'
6
+ #require 'spec/rake/spectask'
7
+ require 'echoe'
8
+
9
+ desc 'Default: run unit tests.'
10
+ task :default => :test
11
+
12
+ Echoe.new('no_fuzz') do |p|
13
+ p.author = "Bjørn Arild Mæland"
14
+ p.email = "bjorn.maeland@gmail.com"
15
+ p.summary = "No Fuzz"
16
+ p.url = "http://www.github.com/Chrononaut/no_fuzz/"
17
+ p.ignore_pattern = FileList[".gitignore"]
18
+ p.include_rakefile = true
19
+ end
20
+
21
+ desc 'Test the no_fuzz plugin.'
22
+ Rake::TestTask.new(:test) do |t|
23
+ t.libs << 'lib'
24
+ t.libs << 'test'
25
+ t.pattern = 'test/**/*_test.rb'
26
+ t.verbose = true
27
+ end
28
+
29
+ DOCUMENTED_FILES = FileList['README.markdown', 'MIT-LICENSE', 'lib/**/*.rb']
30
+
31
+ desc 'Generate documentation for the no_fuzz plugin.'
32
+ Rake::RDocTask.new do |rdoc|
33
+ rdoc.rdoc_dir = 'doc'
34
+ rdoc.title = "HostConnect"
35
+ rdoc.options << '--line-numbers' << '--inline-source' << '--main' << 'README.markdown'
36
+ rdoc.rdoc_files.include(*DOCUMENTED_FILES)
37
+ end
@@ -0,0 +1,5 @@
1
+ Description:
2
+ Creates a migration and a modle for trigram indexing for a given model.
3
+
4
+ Example:
5
+ ./script/generate no_fuzz MODELNAME
@@ -0,0 +1,33 @@
1
+ class NoFuzzGenerator < Rails::Generator::NamedBase
2
+ def manifest
3
+ record do |m|
4
+ m.template "model.rb", "app/models/#{class_name.underscore.downcase}_trigram.rb", {
5
+ :assigns => local_assigns
6
+ }
7
+
8
+ m.migration_template "migration.rb", "db/migrate", {
9
+ :assigns => local_assigns,
10
+ :migration_file_name => local_assigns[:migration_class_name].underscore.downcase
11
+ }
12
+ end
13
+ end
14
+
15
+ private
16
+ def local_custom_name
17
+ class_name.underscore.downcase
18
+ end
19
+
20
+ def gracefully_pluralize(str)
21
+ str.pluralize! if ActiveRecord::Base.pluralize_table_names
22
+ str
23
+ end
24
+
25
+ def local_assigns
26
+ returning(assigns = {}) do
27
+ assigns[:class_name] = local_custom_name.classify
28
+ assigns[:migration_class_name] = "CreateTrigramsTableFor#{assigns[:class_name]}"
29
+ assigns[:table_name] = gracefully_pluralize(local_custom_name + "_trigram")
30
+ assigns[:foreign_key] = (class_name.underscore.downcase + "_id")
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,15 @@
1
+ class <%= migration_name -%> < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :<%= table_name -%>, :force => true do |t|
4
+ t.integer :<%= foreign_key -%>, :null => false
5
+ t.string :tg, :length => 3, :null => false # trigrams
6
+ t.integer :score, :default => 1, :null => false
7
+ end
8
+ add_index :<%= table_name -%>, :tg
9
+ add_index :<%= table_name -%>, :<%= foreign_key %>
10
+ end
11
+
12
+ def self.down
13
+ drop_table :<%= table_name %>
14
+ end
15
+ end
@@ -0,0 +1,2 @@
1
+ class <%= class_name -%>Trigram < ActiveRecord::Base
2
+ end
data/init.rb ADDED
@@ -0,0 +1,2 @@
1
+ # Include hook code here
2
+ require File.dirname(__FILE__) + "/rails/init"
data/install.rb ADDED
@@ -0,0 +1 @@
1
+ # Install hook code here
data/lib/no_fuzz.rb ADDED
@@ -0,0 +1,70 @@
1
+ # TODO:
2
+ # - scores
3
+ # I.e fuzzy {:first_name => 1, :last_name => 2}, last_name gives double score
4
+ # Currently everything gets scored with 1
5
+ # - normalization
6
+ # - weighting of fuzzy_find results
7
+
8
+ module NoFuzz
9
+ def self.included(model)
10
+ model.extend ClassMethods
11
+ end
12
+
13
+ module ClassMethods
14
+ def self.extended(model)
15
+ @@model = model
16
+ end
17
+
18
+ def fuzzy(*fields)
19
+ # put the parameters as instance variable of the model
20
+ @@model.instance_variable_set(:@fuzzy_fields, fields)
21
+ @@model.instance_variable_set(:@fuzzy_ref_id, "#{@@model}_id".downcase)
22
+ @@model.instance_variable_set(:@fuzzy_trigram_model, "#{@@model}Trigram".constantize)
23
+ end
24
+
25
+ def populate_trigram_index
26
+ clear_trigram_index
27
+
28
+ fuzzy_ref_id = self.instance_variable_get(:@fuzzy_ref_id)
29
+ trigram_model = self.instance_variable_get(:@fuzzy_trigram_model)
30
+ fields = self.instance_variable_get(:@fuzzy_fields)
31
+
32
+ fields.each do |f|
33
+ self.all.each do |i|
34
+ word = ' ' + i.send(f)
35
+ (0..word.length-3).each do |idx|
36
+ tg = word[idx,3]
37
+ trigram_model.create(:tg => tg, fuzzy_ref_id => i.id)
38
+ end
39
+ end
40
+ end
41
+ true
42
+ end
43
+
44
+ def clear_trigram_index
45
+ self.instance_variable_get(:@fuzzy_trigram_model).delete_all
46
+ end
47
+
48
+ def fuzzy_find(word, limit = 0)
49
+ fuzzy_ref_id = self.instance_variable_get(:@fuzzy_ref_id)
50
+ trigram_model = self.instance_variable_get(:@fuzzy_trigram_model)
51
+ fields = self.instance_variable_get(:@fuzzy_fields)
52
+
53
+ word = ' ' + word + ' '
54
+ trigrams = (0..word.length-3).collect { |idx| word[idx,3] }
55
+
56
+ # ordered hash of package_id => score pairs
57
+ trigram_groups = trigram_model.sum(:score, :conditions => [ "tg IN (?)", trigrams],
58
+ :group => fuzzy_ref_id.to_s)
59
+
60
+ count = 0
61
+ @res = []
62
+ trigram_groups.sort_by {|a| -a[1]}.each do |group|
63
+ @res << self.find(group[0])
64
+ count += 1
65
+ break if count == limit
66
+ end
67
+ @res
68
+ end
69
+ end
70
+ end
data/no_fuzz.gemspec ADDED
@@ -0,0 +1,35 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{no_fuzz}
5
+ s.version = "0.0.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Bj\303\270rn Arild M\303\246land"]
9
+ s.date = %q{2009-03-30}
10
+ s.description = %q{No Fuzz}
11
+ s.email = %q{bjorn.maeland@gmail.com}
12
+ s.extra_rdoc_files = ["README.markdown", "tasks/no_fuzz_tasks.rake", "CHANGELOG", "lib/no_fuzz.rb"]
13
+ s.files = ["Rakefile", "README.markdown", "tasks/no_fuzz_tasks.rake", "uninstall.rb", "init.rb", "generators/no_fuzz/no_fuzz_generator.rb", "generators/no_fuzz/templates/model.rb", "generators/no_fuzz/templates/migration.rb", "generators/no_fuzz/USAGE", "rails/init.rb", "CHANGELOG", "lib/no_fuzz.rb", "MIT-LICENSE", "install.rb", "test/no_fuzz_test.rb", "test/test_helper.rb", "test/database.yml", "test/schema.rb", "test/test.sqlite3", "Manifest", "no_fuzz.gemspec"]
14
+ s.has_rdoc = true
15
+ s.homepage = %q{http://www.github.com/Chrononaut/no_fuzz/}
16
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "No_fuzz", "--main", "README.markdown"]
17
+ s.require_paths = ["lib"]
18
+ s.rubyforge_project = %q{no_fuzz}
19
+ s.rubygems_version = %q{1.3.1}
20
+ s.summary = %q{No Fuzz}
21
+ s.test_files = ["test/no_fuzz_test.rb", "test/test_helper.rb"]
22
+
23
+ if s.respond_to? :specification_version then
24
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
25
+ s.specification_version = 2
26
+
27
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
28
+ s.add_development_dependency(%q<echoe>, [">= 0"])
29
+ else
30
+ s.add_dependency(%q<echoe>, [">= 0"])
31
+ end
32
+ else
33
+ s.add_dependency(%q<echoe>, [">= 0"])
34
+ end
35
+ end
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'no_fuzz'
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :no_fuzz do
3
+ # # Task goes here
4
+ # end
data/test/database.yml ADDED
@@ -0,0 +1,21 @@
1
+ sqlite:
2
+ :adapter: sqlite
3
+ :dbfile: vendor/plugins/no_fuzz/test/test.sqlite
4
+
5
+ sqlite3:
6
+ :adapter: sqlite3
7
+ :dbfile: test/test.sqlite3
8
+
9
+ postgresql:
10
+ :adapter: postgresql
11
+ :username: postgres
12
+ :password: postgres
13
+ :database: no_fuzz_plugin_test
14
+ :min_messages: ERROR
15
+
16
+ mysql:
17
+ :adapter: mysql
18
+ :host: localhost
19
+ :username: root
20
+ :password: password
21
+ :database: no_fuzz_plugin_test
@@ -0,0 +1,18 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class NoFuzzTest < ActiveSupport::TestCase
4
+
5
+ load_schema
6
+
7
+ class Package < ActiveRecord::Base
8
+ end
9
+
10
+ class PackageTrigram < ActiveRecord::Base
11
+ end
12
+
13
+ def test_schema_has_loaded_correctly
14
+ assert_equal [], Package.all
15
+ assert_equal [], PackageTrigram.all
16
+ end
17
+
18
+ end
data/test/schema.rb ADDED
@@ -0,0 +1,11 @@
1
+ ActiveRecord::Schema.define(:version => 0) do
2
+ create_table :packages, :force => true do |t|
3
+ t.string :name
4
+ end
5
+
6
+ create_table :package_trigrams, :force => true do |t|
7
+ t.integer :package_id
8
+ t.string :tg
9
+ t.integer :score
10
+ end
11
+ end
data/test/test.sqlite3 ADDED
Binary file
@@ -0,0 +1,34 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+ require 'active_record'
4
+ require 'active_support'
5
+ require 'active_support/test_case'
6
+
7
+ def load_schema
8
+ config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
9
+ ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
10
+
11
+ db_adapter = ENV['DB']
12
+
13
+ # no db passed, try one of these fine config-free DBs before bombing.
14
+ db_adapter ||=
15
+ begin
16
+ require 'rubygems'
17
+ require 'sqlite'
18
+ 'sqlite'
19
+ rescue MissingSourceFile
20
+ begin
21
+ require 'sqlite3'
22
+ 'sqlite3'
23
+ rescue MissingSourceFile
24
+ end
25
+ end
26
+
27
+ if db_adapter.nil?
28
+ raise "No DB Adapter selected. Pass the DB= option to pick one, or install Sqlite or Sqlite3."
29
+ end
30
+
31
+ ActiveRecord::Base.establish_connection(config[db_adapter])
32
+ #load(File.dirname(__FILE__) + "/schema.rb")
33
+ require File.dirname(__FILE__) + '/../rails/init.rb'
34
+ end
data/uninstall.rb ADDED
@@ -0,0 +1 @@
1
+ # Uninstall hook code here
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: Chrononaut-no_fuzz
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - "Bj\xC3\xB8rn Arild M\xC3\xA6land"
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-03-30 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: echoe
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description: No Fuzz
26
+ email: bjorn.maeland@gmail.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README.markdown
33
+ - tasks/no_fuzz_tasks.rake
34
+ - CHANGELOG
35
+ - lib/no_fuzz.rb
36
+ files:
37
+ - Rakefile
38
+ - README.markdown
39
+ - tasks/no_fuzz_tasks.rake
40
+ - uninstall.rb
41
+ - init.rb
42
+ - generators/no_fuzz/no_fuzz_generator.rb
43
+ - generators/no_fuzz/templates/model.rb
44
+ - generators/no_fuzz/templates/migration.rb
45
+ - generators/no_fuzz/USAGE
46
+ - rails/init.rb
47
+ - CHANGELOG
48
+ - lib/no_fuzz.rb
49
+ - MIT-LICENSE
50
+ - install.rb
51
+ - test/no_fuzz_test.rb
52
+ - test/test_helper.rb
53
+ - test/database.yml
54
+ - test/schema.rb
55
+ - test/test.sqlite3
56
+ - Manifest
57
+ - no_fuzz.gemspec
58
+ has_rdoc: true
59
+ homepage: http://www.github.com/Chrononaut/no_fuzz/
60
+ post_install_message:
61
+ rdoc_options:
62
+ - --line-numbers
63
+ - --inline-source
64
+ - --title
65
+ - No_fuzz
66
+ - --main
67
+ - README.markdown
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: "0"
75
+ version:
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: "1.2"
81
+ version:
82
+ requirements: []
83
+
84
+ rubyforge_project: no_fuzz
85
+ rubygems_version: 1.2.0
86
+ signing_key:
87
+ specification_version: 2
88
+ summary: No Fuzz
89
+ test_files:
90
+ - test/no_fuzz_test.rb
91
+ - test/test_helper.rb