mongoid_search 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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