mongoid_search 0.1.2 → 0.2.0

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/Gemfile CHANGED
@@ -2,5 +2,7 @@ source 'http://rubygems.org'
2
2
 
3
3
  gem "jeweler"
4
4
  gem "database_cleaner"
5
- gem "mongoid", "2.0.0.beta.18"
6
- gem "rspec", "2.0.0.beta.22"
5
+ gem "mongoid", "~> 2.0.0.beta.19"
6
+ gem "rake", "0.8.7"
7
+ gem "rspec", "2.3.0"
8
+ gem "fast-stemmer", "1.0.0"
@@ -1,44 +1,39 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
- activemodel (3.0.0)
5
- activesupport (= 3.0.0)
4
+ activemodel (3.0.5)
5
+ activesupport (= 3.0.5)
6
6
  builder (~> 2.1.2)
7
- i18n (~> 0.4.1)
8
- activesupport (3.0.0)
9
- bson (1.0.4)
7
+ i18n (~> 0.4)
8
+ activesupport (3.0.5)
9
+ bson (1.2.4)
10
10
  builder (2.1.2)
11
- database_cleaner (0.5.2)
11
+ database_cleaner (0.6.4)
12
12
  diff-lcs (1.1.2)
13
- gemcutter (0.6.1)
13
+ fast-stemmer (1.0.0)
14
14
  git (1.2.5)
15
- i18n (0.4.1)
16
- jeweler (1.4.0)
17
- gemcutter (>= 0.1.0)
15
+ i18n (0.5.0)
16
+ jeweler (1.5.2)
17
+ bundler (~> 1.0.0)
18
18
  git (>= 1.2.5)
19
- rubyforge (>= 2.0.0)
20
- json_pure (1.4.6)
21
- mongo (1.0.7)
22
- bson (>= 1.0.4)
23
- mongoid (2.0.0.beta.18)
24
- activemodel (~> 3.0.0)
25
- bson (= 1.0.4)
26
- mongo (= 1.0.7)
19
+ rake
20
+ mongo (1.2.4)
21
+ bson (>= 1.2.4)
22
+ mongoid (2.0.0.rc.7)
23
+ activemodel (~> 3.0)
24
+ mongo (~> 1.2)
27
25
  tzinfo (~> 0.3.22)
28
26
  will_paginate (~> 3.0.pre)
29
- rspec (2.0.0.beta.22)
30
- rspec-core (= 2.0.0.beta.22)
31
- rspec-expectations (= 2.0.0.beta.22)
32
- rspec-mocks (= 2.0.0.beta.22)
33
- rspec-core (2.0.0.beta.22)
34
- rspec-expectations (2.0.0.beta.22)
35
- diff-lcs (>= 1.1.2)
36
- rspec-mocks (2.0.0.beta.22)
37
- rspec-core (= 2.0.0.beta.22)
38
- rspec-expectations (= 2.0.0.beta.22)
39
- rubyforge (2.0.4)
40
- json_pure (>= 1.1.7)
41
- tzinfo (0.3.23)
27
+ rake (0.8.7)
28
+ rspec (2.3.0)
29
+ rspec-core (~> 2.3.0)
30
+ rspec-expectations (~> 2.3.0)
31
+ rspec-mocks (~> 2.3.0)
32
+ rspec-core (2.3.1)
33
+ rspec-expectations (2.3.0)
34
+ diff-lcs (~> 1.1.2)
35
+ rspec-mocks (2.3.0)
36
+ tzinfo (0.3.24)
42
37
  will_paginate (3.0.pre2)
43
38
 
44
39
  PLATFORMS
@@ -46,6 +41,8 @@ PLATFORMS
46
41
 
47
42
  DEPENDENCIES
48
43
  database_cleaner
44
+ fast-stemmer (= 1.0.0)
49
45
  jeweler
50
- mongoid (= 2.0.0.beta.18)
51
- rspec (= 2.0.0.beta.22)
46
+ mongoid (~> 2.0.0.beta.19)
47
+ rake (= 0.8.7)
48
+ rspec (= 2.3.0)
data/README.md CHANGED
@@ -24,8 +24,9 @@ Examples
24
24
  field :name
25
25
 
26
26
  references_many :tags
27
+ refereced_in :category
27
28
 
28
- search_in :brand, :name, :tags => :name
29
+ search_in :brand, :name, :tags => :name, :category => :name
29
30
  end
30
31
 
31
32
  class Tag
@@ -34,6 +35,13 @@ Examples
34
35
 
35
36
  referenced_in :product
36
37
  end
38
+
39
+ class Category
40
+ include Mongoid::Document
41
+ field :name
42
+
43
+ references_many :products
44
+ end
37
45
 
38
46
  Now when you save a product, you get a _keywords field automatically:
39
47
 
@@ -58,10 +66,10 @@ Note that the search is case insensitive, and accept partial searching too:
58
66
  Options
59
67
  -------
60
68
 
61
- :match:
62
- :any - match any occurrence
63
- :all - match all ocurrences
64
- Default is :any.
69
+ match:
70
+ _:any_ - match any occurrence
71
+ _:all_ - match all ocurrences
72
+ Default is _:any_.
65
73
 
66
74
  search_in :brand, :name, { :tags => :name }, { :match => :any }
67
75
 
@@ -72,3 +80,21 @@ Options
72
80
 
73
81
  Product.search("apple motorola").size
74
82
  => 0
83
+
84
+ allow_empty_search:
85
+ _true_ - match any occurrence
86
+ _false_ - match all ocurrences
87
+ Default is _false_.
88
+
89
+ search_in :brand, :name, { :tags => :name }, { :allow_empty_search => true }
90
+
91
+ Product.search("").size
92
+ => 1
93
+
94
+ TODO
95
+ ----
96
+
97
+ * Strip html with sanitize (https://github.com/rgrove/sanitize)
98
+ * Test relevant search
99
+ * Move all configurations to a configuration file. Maybe /config/mongoid_search.yml.
100
+
data/Rakefile CHANGED
@@ -10,8 +10,8 @@ begin
10
10
  gem.email = "mauricio@papodenerd.net"
11
11
  gem.homepage = "http://www.papodenerd.net/mongoid-search-full-text-search-for-your-mongoid-models/"
12
12
  gem.authors = ["Mauricio Zaffari"]
13
- gem.add_dependency("mongoid", ["~> 2.0.0.beta"])
14
- gem.add_development_dependency "rspec", ">= 1.2.9"
13
+ gem.add_dependency("mongoid", ["~> 2.0.0"])
14
+ gem.add_development_dependency "rspec", ">= 2.0.1"
15
15
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
16
  end
17
17
  Jeweler::GemcutterTasks.new
@@ -19,10 +19,10 @@ rescue LoadError
19
19
  puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
20
20
  end
21
21
 
22
- require 'spec/rake/spectask'
23
- Spec::Rake::SpecTask.new(:spec) do |spec|
24
- spec.libs << 'lib' << 'spec'
25
- spec.spec_files = FileList['spec/**/*_spec.rb']
22
+ require 'rspec/core/rake_task'
23
+ RSpec::Core::RakeTask.new(:spec) do |spec|
24
+ spec.rspec_opts = ["-c", "-f progress"]
25
+ spec.pattern = 'spec/**/*_spec.rb'
26
26
  end
27
27
 
28
28
  task :default => :spec
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.2
1
+ 0.2.0
@@ -1,2 +1,2 @@
1
- require 'mongoid_search/keywords_extractor'
1
+ require 'mongoid_search/util'
2
2
  require 'mongoid_search/mongoid_search'
@@ -2,15 +2,19 @@ module Mongoid::Search
2
2
  extend ActiveSupport::Concern
3
3
 
4
4
  included do
5
- cattr_accessor :search_fields, :match
5
+ cattr_accessor :search_fields, :match, :allow_empty_search, :relevant_search, :stem_keywords, :ignore_list
6
6
  end
7
7
 
8
8
  module ClassMethods #:nodoc:
9
9
  # Set a field or a number of fields as sources for search
10
10
  def search_in(*args)
11
- options = args.last.is_a?(Hash) && (args.last.keys.first == :match) ? args.pop : {}
12
- self.match = [:any, :all].include?(options[:match]) ? options[:match] : :any
13
- self.search_fields = args
11
+ options = args.last.is_a?(Hash) && [:match, :allow_empty_search, :relevant_search, :stem_keywords, :ignore_list].include?(args.last.keys.first) ? args.pop : {}
12
+ self.match = [:any, :all].include?(options[:match]) ? options[:match] : :any
13
+ self.allow_empty_search = [true, false].include?(options[:allow_empty_search]) ? options[:allow_empty_search] : false
14
+ self.relevant_search = [true, false].include?(options[:relevant_search]) ? options[:allow_empty_search] : false
15
+ self.stem_keywords = [true, false].include?(options[:stem_keywords]) ? options[:allow_empty_search] : false
16
+ self.ignore_list = YAML.load(File.open(options[:ignore_list]))["ignorelist"] if options[:ignore_list].present?
17
+ self.search_fields = args
14
18
 
15
19
  field :_keywords, :type => Array
16
20
  index :_keywords
@@ -18,20 +22,85 @@ module Mongoid::Search
18
22
  before_save :set_keywords
19
23
  end
20
24
 
21
- def search(query)
22
- self.send("#{self.match.to_s}_in", :_keywords => KeywordsExtractor.extract(query).map { |q| /#{q}/ })
25
+ def search(query, options={})
26
+ if relevant_search
27
+ search_relevant(query, options)
28
+ else
29
+ search_without_relevance(query, options)
30
+ end
31
+ end
32
+
33
+ def search_without_relevance(query, options={})
34
+ return self.all if query.blank? && allow_empty_search
35
+ self.send("#{(options[:match]||self.match).to_s}_in", :_keywords => Util.keywords(query, stem_keywords, ignore_list).map { |q| /#{q}/ })
36
+ end
37
+
38
+ def search_relevant(query, options={})
39
+ return self.all if query.blank? && allow_empty_search
40
+
41
+ keywords = Util.keywords(query, stem_keywords, ignore_list)
42
+
43
+ map = <<-EOS
44
+ function() {
45
+ var entries = 0
46
+ for(i in keywords)
47
+ for(j in this._keywords) {
48
+ if(this._keywords[j] == keywords[i])
49
+ entries++
50
+ }
51
+ if(entries > 0)
52
+ emit(this._id, entries)
53
+ }
54
+ EOS
55
+ reduce = <<-EOS
56
+ function(key, values) {
57
+ return(values[0])
58
+ }
59
+ EOS
60
+
61
+ #raise [self.class, self.inspect].inspect
62
+
63
+ kw_conditions = keywords.map do |kw|
64
+ {:_keywords => kw}
65
+ end
66
+
67
+ criteria = self.any_of(*kw_conditions)
68
+
69
+ query = criteria.selector
70
+
71
+ options.delete(:limit)
72
+ options.delete(:skip)
73
+ options.merge! :scope => {:keywords => keywords}, :query => query
74
+
75
+ res = collection.map_reduce(map, reduce, options)
76
+
77
+ res.find.sort(['value', -1]) # Cursor
23
78
  end
24
79
  end
25
80
 
26
81
  private
27
-
82
+
83
+ # TODO: This need some refatoring..
28
84
  def set_keywords
29
85
  self._keywords = self.search_fields.map do |field|
30
86
  if field.is_a?(Hash)
31
- field.keys.map { |key| self.send(key).map(&field[key]).map { |t| KeywordsExtractor.extract t } }
87
+ field.keys.map do |key|
88
+ attribute = self.send(key)
89
+ method = field[key]
90
+ if attribute.is_a?(Array)
91
+ if method.is_a?(Array)
92
+ method.map {|m| attribute.map { |a| Util.keywords a.send(m), stem_keywords, ignore_list } }
93
+ else
94
+ attribute.map(&method).map { |t| Util.keywords t, stem_keywords, ignore_list }
95
+ end
96
+ else
97
+ Util.keywords(attribute.send(method), stem_keywords, ignore_list)
98
+ end
99
+ end
32
100
  else
33
- KeywordsExtractor.extract(self.send(field))
101
+ text = self[field]
102
+ Util.keywords(text, stem_keywords, ignore_list) unless text.nil?
34
103
  end
35
- end.flatten.compact.uniq
104
+ end.flatten.compact.sort
36
105
  end
37
- end
106
+ end
@@ -0,0 +1,19 @@
1
+ module Util
2
+
3
+ def self.keywords(text, stem_keywords, ignore_list)
4
+ return [] if text.blank?
5
+ text = text.
6
+ mb_chars.
7
+ normalize(:kd).
8
+ to_s.
9
+ gsub(/[._:;'"`,?|+={}()!@#%^&*<>~\$\-\\\/\[\]]/, ' '). # strip punctuation
10
+ gsub(/[^[:alpha:]\s]/,''). # strip accents
11
+ downcase.
12
+ split(' ').
13
+ reject { |word| word.size < 2 }
14
+ text = text.reject { |word| ignore_list.include?(word) } unless ignore_list.blank?
15
+ text = text.map(&:stem) if stem_keywords
16
+ text
17
+ end
18
+
19
+ end
@@ -1,52 +1,54 @@
1
1
  # Generated by jeweler
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{mongoid_search}
8
- s.version = "0.1.2"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Mauricio Zaffari"]
12
- s.date = %q{2010-09-17}
12
+ s.date = %q{2011-03-28}
13
13
  s.description = %q{Simple full text search implementation.}
14
14
  s.email = %q{mauricio@papodenerd.net}
15
15
  s.extra_rdoc_files = [
16
16
  "LICENSE",
17
- "README.md"
17
+ "README.md"
18
18
  ]
19
19
  s.files = [
20
20
  ".document",
21
- ".gitignore",
22
- "Gemfile",
23
- "Gemfile.lock",
24
- "LICENSE",
25
- "README.md",
26
- "Rakefile",
27
- "VERSION",
28
- "lib/mongoid_search.rb",
29
- "lib/mongoid_search/keywords_extractor.rb",
30
- "lib/mongoid_search/mongoid_search.rb",
31
- "mongoid_search.gemspec",
32
- "spec/keywords_extractor_spec.rb",
33
- "spec/models/product.rb",
34
- "spec/models/tag.rb",
35
- "spec/mongoid_search_spec.rb",
36
- "spec/spec.opts",
37
- "spec/spec_helper.rb"
21
+ "Gemfile",
22
+ "Gemfile.lock",
23
+ "LICENSE",
24
+ "README.md",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "lib/mongoid_search.rb",
28
+ "lib/mongoid_search/mongoid_search.rb",
29
+ "lib/mongoid_search/util.rb",
30
+ "mongoid_search.gemspec",
31
+ "spec/config/ignorelist.yml",
32
+ "spec/models/category.rb",
33
+ "spec/models/product.rb",
34
+ "spec/models/subproduct.rb",
35
+ "spec/models/tag.rb",
36
+ "spec/mongoid_search_spec.rb",
37
+ "spec/spec_helper.rb",
38
+ "spec/util_spec.rb"
38
39
  ]
39
40
  s.homepage = %q{http://www.papodenerd.net/mongoid-search-full-text-search-for-your-mongoid-models/}
40
- s.rdoc_options = ["--charset=UTF-8"]
41
41
  s.require_paths = ["lib"]
42
42
  s.rubygems_version = %q{1.3.7}
43
43
  s.summary = %q{Search implementation for Mongoid ORM}
44
44
  s.test_files = [
45
- "spec/keywords_extractor_spec.rb",
46
- "spec/models/product.rb",
47
- "spec/models/tag.rb",
48
- "spec/mongoid_search_spec.rb",
49
- "spec/spec_helper.rb"
45
+ "spec/models/category.rb",
46
+ "spec/models/product.rb",
47
+ "spec/models/subproduct.rb",
48
+ "spec/models/tag.rb",
49
+ "spec/mongoid_search_spec.rb",
50
+ "spec/spec_helper.rb",
51
+ "spec/util_spec.rb"
50
52
  ]
51
53
 
52
54
  if s.respond_to? :specification_version then
@@ -54,15 +56,33 @@ Gem::Specification.new do |s|
54
56
  s.specification_version = 3
55
57
 
56
58
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
57
- s.add_runtime_dependency(%q<mongoid>, ["~> 2.0.0.beta"])
58
- s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
59
+ s.add_runtime_dependency(%q<jeweler>, [">= 0"])
60
+ s.add_runtime_dependency(%q<database_cleaner>, [">= 0"])
61
+ s.add_runtime_dependency(%q<mongoid>, ["~> 2.0.0.beta.19"])
62
+ s.add_runtime_dependency(%q<rake>, ["= 0.8.7"])
63
+ s.add_runtime_dependency(%q<rspec>, ["= 2.3.0"])
64
+ s.add_runtime_dependency(%q<fast-stemmer>, ["= 1.0.0"])
65
+ s.add_runtime_dependency(%q<mongoid>, ["~> 2.0.0"])
66
+ s.add_development_dependency(%q<rspec>, [">= 2.0.1"])
59
67
  else
60
- s.add_dependency(%q<mongoid>, ["~> 2.0.0.beta"])
61
- s.add_dependency(%q<rspec>, [">= 1.2.9"])
68
+ s.add_dependency(%q<jeweler>, [">= 0"])
69
+ s.add_dependency(%q<database_cleaner>, [">= 0"])
70
+ s.add_dependency(%q<mongoid>, ["~> 2.0.0.beta.19"])
71
+ s.add_dependency(%q<rake>, ["= 0.8.7"])
72
+ s.add_dependency(%q<rspec>, ["= 2.3.0"])
73
+ s.add_dependency(%q<fast-stemmer>, ["= 1.0.0"])
74
+ s.add_dependency(%q<mongoid>, ["~> 2.0.0"])
75
+ s.add_dependency(%q<rspec>, [">= 2.0.1"])
62
76
  end
63
77
  else
64
- s.add_dependency(%q<mongoid>, ["~> 2.0.0.beta"])
65
- s.add_dependency(%q<rspec>, [">= 1.2.9"])
78
+ s.add_dependency(%q<jeweler>, [">= 0"])
79
+ s.add_dependency(%q<database_cleaner>, [">= 0"])
80
+ s.add_dependency(%q<mongoid>, ["~> 2.0.0.beta.19"])
81
+ s.add_dependency(%q<rake>, ["= 0.8.7"])
82
+ s.add_dependency(%q<rspec>, ["= 2.3.0"])
83
+ s.add_dependency(%q<fast-stemmer>, ["= 1.0.0"])
84
+ s.add_dependency(%q<mongoid>, ["~> 2.0.0"])
85
+ s.add_dependency(%q<rspec>, [">= 2.0.1"])
66
86
  end
67
87
  end
68
88
 
@@ -0,0 +1,2 @@
1
+ ignorelist:
2
+ amazing, awesome
@@ -0,0 +1,6 @@
1
+ class Category
2
+ include Mongoid::Document
3
+ field :name
4
+
5
+ references_many :products
6
+ end
@@ -5,6 +5,8 @@ class Product
5
5
  field :name
6
6
 
7
7
  references_many :tags
8
+ referenced_in :category
9
+ embeds_many :subproducts
8
10
 
9
- search_in :brand, :name, :tags => :name
11
+ search_in :brand, :name, :outlet, :tags => :name, :category => :name, :subproducts => [:brand, :name]
10
12
  end
@@ -0,0 +1,8 @@
1
+ class Subproduct
2
+ include Mongoid::Document
3
+
4
+ field :brand
5
+ field :name
6
+
7
+ embedded_in :product, :inverse_of => :subproducts
8
+ end
@@ -5,16 +5,56 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
5
5
  describe Mongoid::Search do
6
6
 
7
7
  before(:each) do
8
- @product = Product.create :brand => "Apple", :name => "iPhone", :tags => ["Amazing", "Awesome", "Olé"].map { |tag| Tag.new(:name => tag) }
8
+ Product.stem_keywords = false
9
+ Product.ignore_list = nil
10
+ @product = Product.create :brand => "Apple",
11
+ :name => "iPhone",
12
+ :tags => ["Amazing", "Awesome", "Olé"].map { |tag| Tag.new(:name => tag) },
13
+ :category => Category.new(:name => "Mobile"),
14
+ :subproducts => [Subproduct.new(:brand => "Apple", :name => "Craddle")]
15
+ end
16
+
17
+ context "utf-8 characters" do
18
+ before(:each) {
19
+ Product.stem_keywords = false
20
+ Product.ignore_list = nil
21
+ @product = Product.create :brand => "Эльбрус",
22
+ :name => "Процессор",
23
+ :tags => ["Amazing", "Awesome", "Olé"].map { |tag| Tag.new(:name => tag) },
24
+ :category => Category.new(:name => "процессоры"),
25
+ :subproducts => []
26
+ }
27
+
28
+ it "should leave utf8 characters" do
29
+ @product._keywords.should == ["amazing", "awesome", "ole", "Процессор", "Эльбрус", "процессоры"]
30
+ end
9
31
  end
10
32
 
11
33
  it "should set the _keywords field" do
12
- @product._keywords.should == ["apple", "iphone", "amazing", "awesome", "ole"]
34
+ @product._keywords.should == ["amazing", "apple", "apple", "awesome", "craddle", "iphone", "mobile", "ole"]
35
+ end
36
+
37
+ it "should set the _keywords field with stemmed words if stem is enabled" do
38
+ Product.stem_keywords = true
39
+ @product.save!
40
+ @product._keywords.should == ["amaz", "appl", "appl", "awesom", "craddl", "iphon", "mobil", "ol"]
41
+ end
42
+
43
+ it "should ignore keywords in an ignore list" do
44
+ Product.ignore_list = YAML.load(File.open(File.dirname(__FILE__) + '/config/ignorelist.yml'))["ignorelist"]
45
+ @product.save!
46
+ @product._keywords.should == ["apple", "apple", "craddle", "iphone", "mobile", "ole"]
13
47
  end
14
48
 
15
49
  it "should return results in search" do
16
50
  Product.search("apple").size.should == 1
17
51
  end
52
+
53
+ it "should return results in search for dynamic attribute" do
54
+ @product[:outlet] = "online shop"
55
+ @product.save!
56
+ Product.search("online").size.should == 1
57
+ end
18
58
 
19
59
  it "should return results in search even searching a accented word" do
20
60
  Product.search("Ole").size.should == 1
@@ -37,4 +77,26 @@ describe Mongoid::Search do
37
77
  Product.match = :all
38
78
  Product.search("apple motorola").size.should == 0
39
79
  end
80
+
81
+ it "should return results for any matching word, using :match => :all, passing :match => :any to .search" do
82
+ Product.match = :all
83
+ Product.search("apple motorola", :match => :any).size.should == 1
84
+ end
85
+
86
+ it "should not return results when all words do not match, passing :match => :all to .search" do
87
+ Product.search("apple motorola", :match => :all).size.should == 0
88
+ end
89
+
90
+ it "should return no results when a blank search is made" do
91
+ Product.search("").size.should == 0
92
+ end
93
+
94
+ it "should return results when a blank search is made when :allow_empty_search is true" do
95
+ Product.allow_empty_search = true
96
+ Product.search("").size.should == 1
97
+ end
98
+
99
+ it "should search for embedded documents" do
100
+ Product.search("craddle").size.should == 1
101
+ end
40
102
  end
@@ -2,6 +2,8 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
2
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
3
  require 'mongoid'
4
4
  require 'database_cleaner'
5
+ require 'fast_stemmer'
6
+ require 'yaml'
5
7
  require 'mongoid_search'
6
8
 
7
9
  Mongoid.configure do |config|
@@ -11,9 +13,9 @@ end
11
13
 
12
14
  Dir["#{File.dirname(__FILE__)}/models/*.rb"].each { |file| require file }
13
15
 
14
- DatabaseCleaner.orm = "mongoid"
16
+ DatabaseCleaner.orm = :mongoid
15
17
 
16
- Spec::Runner.configure do |config|
18
+ RSpec.configure do |config|
17
19
  config.before(:all) do
18
20
  DatabaseCleaner.strategy = :truncation
19
21
  end
@@ -0,0 +1,40 @@
1
+ # encoding: utf-8
2
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
3
+
4
+ describe Util do
5
+ it "should return an empty array if no text is passed" do
6
+ Util.keywords("", false, "").should == []
7
+ end
8
+
9
+ it "should return an array of keywords" do
10
+ Util.keywords("keyword", false, "").class.should == Array
11
+ end
12
+
13
+ it "should return an array of strings" do
14
+ Util.keywords("keyword", false, "").first.class.should == String
15
+ end
16
+
17
+ it "should remove accents from the text passed" do
18
+ Util.keywords("café", false, "").should == ["cafe"]
19
+ end
20
+
21
+ it "should downcase the text passed" do
22
+ Util.keywords("CaFé", false, "").should == ["cafe"]
23
+ end
24
+
25
+ it "should split whitespaces, hifens, dots, underlines, etc.." do
26
+ Util.keywords("CaFé-express.com delicious;come visit, and 'win' an \"iPad\"", false, "").should == ["cafe", "express", "com", "delicious", "come", "visit", "and", "win", "an", "ipad"]
27
+ end
28
+
29
+ it "should stem keywords" do
30
+ Util.keywords("A runner running and eating", true, "").should == ["runner", "run", "and", "eat"]
31
+ end
32
+
33
+ it "should ignore keywords from ignore list" do
34
+ Util.keywords("An amazing awesome runner running and eating", true, YAML.load(File.open(File.dirname(__FILE__) + '/config/ignorelist.yml'))["ignorelist"]).should == ["an", "runner", "run", "and", "eat"]
35
+ end
36
+
37
+ it "should ignore keywords with less than two words" do
38
+ Util.keywords("A runner running", false, "").should_not include "a"
39
+ end
40
+ end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 1
8
7
  - 2
9
- version: 0.1.2
8
+ - 0
9
+ version: 0.2.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Mauricio Zaffari
@@ -14,13 +14,38 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-09-17 00:00:00 -03:00
17
+ date: 2011-03-28 00:00:00 -03:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
- name: mongoid
22
- prerelease: false
21
+ name: jeweler
23
22
  requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :runtime
31
+ prerelease: false
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: database_cleaner
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ none: false
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ segments:
41
+ - 0
42
+ version: "0"
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: *id002
46
+ - !ruby/object:Gem::Dependency
47
+ name: mongoid
48
+ requirement: &id003 !ruby/object:Gem::Requirement
24
49
  none: false
25
50
  requirements:
26
51
  - - ~>
@@ -30,24 +55,86 @@ dependencies:
30
55
  - 0
31
56
  - 0
32
57
  - beta
33
- version: 2.0.0.beta
58
+ - 19
59
+ version: 2.0.0.beta.19
34
60
  type: :runtime
35
- version_requirements: *id001
61
+ prerelease: false
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: rake
65
+ requirement: &id004 !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - "="
69
+ - !ruby/object:Gem::Version
70
+ segments:
71
+ - 0
72
+ - 8
73
+ - 7
74
+ version: 0.8.7
75
+ type: :runtime
76
+ prerelease: false
77
+ version_requirements: *id004
36
78
  - !ruby/object:Gem::Dependency
37
79
  name: rspec
80
+ requirement: &id005 !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - "="
84
+ - !ruby/object:Gem::Version
85
+ segments:
86
+ - 2
87
+ - 3
88
+ - 0
89
+ version: 2.3.0
90
+ type: :runtime
38
91
  prerelease: false
39
- requirement: &id002 !ruby/object:Gem::Requirement
92
+ version_requirements: *id005
93
+ - !ruby/object:Gem::Dependency
94
+ name: fast-stemmer
95
+ requirement: &id006 !ruby/object:Gem::Requirement
40
96
  none: false
41
97
  requirements:
42
- - - ">="
98
+ - - "="
43
99
  - !ruby/object:Gem::Version
44
100
  segments:
45
101
  - 1
102
+ - 0
103
+ - 0
104
+ version: 1.0.0
105
+ type: :runtime
106
+ prerelease: false
107
+ version_requirements: *id006
108
+ - !ruby/object:Gem::Dependency
109
+ name: mongoid
110
+ requirement: &id007 !ruby/object:Gem::Requirement
111
+ none: false
112
+ requirements:
113
+ - - ~>
114
+ - !ruby/object:Gem::Version
115
+ segments:
116
+ - 2
117
+ - 0
118
+ - 0
119
+ version: 2.0.0
120
+ type: :runtime
121
+ prerelease: false
122
+ version_requirements: *id007
123
+ - !ruby/object:Gem::Dependency
124
+ name: rspec
125
+ requirement: &id008 !ruby/object:Gem::Requirement
126
+ none: false
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ segments:
46
131
  - 2
47
- - 9
48
- version: 1.2.9
132
+ - 0
133
+ - 1
134
+ version: 2.0.1
49
135
  type: :development
50
- version_requirements: *id002
136
+ prerelease: false
137
+ version_requirements: *id008
51
138
  description: Simple full text search implementation.
52
139
  email: mauricio@papodenerd.net
53
140
  executables: []
@@ -59,7 +146,6 @@ extra_rdoc_files:
59
146
  - README.md
60
147
  files:
61
148
  - .document
62
- - .gitignore
63
149
  - Gemfile
64
150
  - Gemfile.lock
65
151
  - LICENSE
@@ -67,22 +153,24 @@ files:
67
153
  - Rakefile
68
154
  - VERSION
69
155
  - lib/mongoid_search.rb
70
- - lib/mongoid_search/keywords_extractor.rb
71
156
  - lib/mongoid_search/mongoid_search.rb
157
+ - lib/mongoid_search/util.rb
72
158
  - mongoid_search.gemspec
73
- - spec/keywords_extractor_spec.rb
159
+ - spec/config/ignorelist.yml
160
+ - spec/models/category.rb
74
161
  - spec/models/product.rb
162
+ - spec/models/subproduct.rb
75
163
  - spec/models/tag.rb
76
164
  - spec/mongoid_search_spec.rb
77
- - spec/spec.opts
78
165
  - spec/spec_helper.rb
166
+ - spec/util_spec.rb
79
167
  has_rdoc: true
80
168
  homepage: http://www.papodenerd.net/mongoid-search-full-text-search-for-your-mongoid-models/
81
169
  licenses: []
82
170
 
83
171
  post_install_message:
84
- rdoc_options:
85
- - --charset=UTF-8
172
+ rdoc_options: []
173
+
86
174
  require_paths:
87
175
  - lib
88
176
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -109,8 +197,10 @@ signing_key:
109
197
  specification_version: 3
110
198
  summary: Search implementation for Mongoid ORM
111
199
  test_files:
112
- - spec/keywords_extractor_spec.rb
200
+ - spec/models/category.rb
113
201
  - spec/models/product.rb
202
+ - spec/models/subproduct.rb
114
203
  - spec/models/tag.rb
115
204
  - spec/mongoid_search_spec.rb
116
205
  - spec/spec_helper.rb
206
+ - spec/util_spec.rb
data/.gitignore DELETED
@@ -1,22 +0,0 @@
1
- ## MAC OS
2
- .DS_Store
3
-
4
- ## TEXTMATE
5
- *.tmproj
6
- tmtags
7
-
8
- ## EMACS
9
- *~
10
- \#*
11
- .\#*
12
-
13
- ## VIM
14
- *.swp
15
-
16
- ## PROJECT::GENERAL
17
- coverage
18
- rdoc
19
- pkg
20
-
21
- ## PROJECT::SPECIFIC
22
- .bundle
@@ -1,6 +0,0 @@
1
- class KeywordsExtractor
2
- def self.extract(text)
3
- return if text.blank?
4
- text.mb_chars.normalize(:kd).to_s.gsub(/[^\x00-\x7F]/,'').downcase.split(/[\s\.\-_]+/)
5
- end
6
- end
@@ -1,28 +0,0 @@
1
- # encoding: utf-8
2
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
3
-
4
- describe KeywordsExtractor do
5
- it "should return if no text is passed" do
6
- KeywordsExtractor.extract("").should == nil
7
- end
8
-
9
- it "should return an array of keywords" do
10
- KeywordsExtractor.extract("keyword").class.should == Array
11
- end
12
-
13
- it "should return an array of strings" do
14
- KeywordsExtractor.extract("keyword").first.class.should == String
15
- end
16
-
17
- it "should remove accents from the text passed" do
18
- KeywordsExtractor.extract("café").should == ["cafe"]
19
- end
20
-
21
- it "should downcase the text passed" do
22
- KeywordsExtractor.extract("CaFé").should == ["cafe"]
23
- end
24
-
25
- it "should split whitespaces, hifens, dots and underlines" do
26
- KeywordsExtractor.extract("CaFé-express.com delicious").should == ["cafe", "express", "com", "delicious"]
27
- end
28
- end
@@ -1 +0,0 @@
1
- --color