mongoid_search 0.2.6 → 0.2.7

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.
@@ -0,0 +1,20 @@
1
+ class Log
2
+ cattr_accessor :silent
3
+
4
+ def self.log(message)
5
+ print message unless silent
6
+ end
7
+
8
+ def self.red(text)
9
+ log(colorize(text, 31))
10
+ end
11
+
12
+ def self.green(text)
13
+ log(colorize(text, 32))
14
+ end
15
+
16
+ private
17
+ def self.colorize(text, code)
18
+ "\033[#{code}m#{text}\033[0m"
19
+ end
20
+ end
@@ -5,6 +5,15 @@ module Mongoid::Search
5
5
  cattr_accessor :search_fields, :match, :allow_empty_search, :relevant_search, :stem_keywords, :ignore_list
6
6
  end
7
7
 
8
+ def self.included(base)
9
+ @classes ||= []
10
+ @classes << base
11
+ end
12
+
13
+ def self.classes
14
+ @classes
15
+ end
16
+
8
17
  module ClassMethods #:nodoc:
9
18
  # Set a field or a number of fields as sources for search
10
19
  def search_in(*args)
@@ -17,7 +26,7 @@ module Mongoid::Search
17
26
  self.search_fields = (self.search_fields || []).concat args
18
27
 
19
28
  field :_keywords, :type => Array
20
- index :_keywords, background: true
29
+ index :_keywords, :background => true
21
30
 
22
31
  before_save :set_keywords
23
32
  end
@@ -29,22 +38,20 @@ module Mongoid::Search
29
38
  search_without_relevance(query, options)
30
39
  end
31
40
  end
32
-
41
+
33
42
  # Mongoid 2.0.0 introduces Criteria.seach so we need to provide
34
43
  # alternate method
35
44
  alias csearch search
36
45
 
37
46
  def search_without_relevance(query, options={})
38
47
  return criteria.all if query.blank? && allow_empty_search
39
- criteria.send("#{(options[:match]||self.match).to_s}_in", :_keywords => Util.keywords(query, stem_keywords, ignore_list).map { |q| /#{q}/ })
48
+ criteria.send("#{(options[:match]||self.match).to_s}_in", :_keywords => Util.normalize_keywords(query, stem_keywords, ignore_list).map { |q| /#{q}/ })
40
49
  end
41
-
42
- # I know what this method should do, but I don't really know what it does.
43
- # It was a pull from another fork, with no tests on it. Proably should be rewrited (and tested).
50
+
44
51
  def search_relevant(query, options={})
45
52
  return criteria.all if query.blank? && allow_empty_search
46
53
 
47
- keywords = Util.keywords(query, stem_keywords, ignore_list)
54
+ keywords = Util.normalize_keywords(query, stem_keywords, ignore_list)
48
55
 
49
56
  map = <<-EOS
50
57
  function() {
@@ -82,32 +89,25 @@ module Mongoid::Search
82
89
  # res.find.sort(['value', -1]) # Cursor
83
90
  collection.map_reduce(map, reduce, options)
84
91
  end
92
+
93
+ # Goes through all documents in the class that includes Mongoid::Search
94
+ # and indexes the keywords.
95
+ def index_keywords!
96
+ all.each { |d| d.index_keywords! ? Log.green(".") : Log.red("F") }
97
+ end
85
98
  end
86
99
 
87
- private
100
+ module InstanceMethods #:nodoc:
101
+ # Indexes the document keywords
102
+ def index_keywords!
103
+ update_attribute(:_keywords, set_keywords)
104
+ end
105
+ end
88
106
 
89
- # TODO: This need some refactoring..
107
+ private
90
108
  def set_keywords
91
109
  self._keywords = self.search_fields.map do |field|
92
- if field.is_a?(Hash)
93
- field.keys.map do |key|
94
- attribute = self.send(key)
95
- method = field[key]
96
- if attribute.is_a?(Array)
97
- if method.is_a?(Array)
98
- method.map {|m| attribute.map { |a| Util.keywords a.send(m), stem_keywords, ignore_list } }
99
- else
100
- attribute.map(&method).map { |t| Util.keywords t, stem_keywords, ignore_list }
101
- end
102
- else
103
- Util.keywords(attribute.send(method), stem_keywords, ignore_list)
104
- end
105
- end
106
- else
107
- value = self[field]
108
- value = value.join(' ') if value.respond_to?(:join)
109
- Util.keywords(value, stem_keywords, ignore_list) if value
110
- end
110
+ Util.keywords(self, field, stem_keywords, ignore_list)
111
111
  end.flatten.reject{|k| k.nil? || k.empty?}.uniq.sort
112
112
  end
113
113
  end
@@ -0,0 +1,10 @@
1
+ require 'mongoid_search'
2
+ require 'rails'
3
+
4
+ module Mongoid::Search
5
+ class Railtie < Rails::Railtie
6
+ rake_tasks do
7
+ Dir[File.join(File.dirname(__FILE__), '../../tasks/*.rake')].each { |f| load f }
8
+ end
9
+ end
10
+ end
@@ -1,13 +1,37 @@
1
1
  module Util
2
2
 
3
- def self.keywords(text, stem_keywords, ignore_list)
3
+ def self.keywords(klass, field, stem_keywords, ignore_list)
4
+ if field.is_a?(Hash)
5
+ field.keys.map do |key|
6
+ attribute = klass.send(key)
7
+ unless attribute.blank?
8
+ method = field[key]
9
+ if attribute.is_a?(Array)
10
+ if method.is_a?(Array)
11
+ method.map {|m| attribute.map { |a| Util.normalize_keywords a.send(m), stem_keywords, ignore_list } }
12
+ else
13
+ attribute.map(&method).map { |t| Util.normalize_keywords t, stem_keywords, ignore_list }
14
+ end
15
+ else
16
+ Util.normalize_keywords(attribute.send(method), stem_keywords, ignore_list)
17
+ end
18
+ end
19
+ end
20
+ else
21
+ value = klass[field]
22
+ value = value.join(' ') if value.respond_to?(:join)
23
+ Util.normalize_keywords(value, stem_keywords, ignore_list) if value
24
+ end
25
+ end
26
+
27
+ def self.normalize_keywords(text, stem_keywords, ignore_list)
4
28
  return [] if text.blank?
5
29
  text = text.to_s.
6
30
  mb_chars.
7
31
  normalize(:kd).
8
32
  to_s.
9
33
  gsub(/[._:;'"`,?|+={}()!@#%^&*<>~\$\-\\\/\[\]]/, ' '). # strip punctuation
10
- gsub(/[^[:alnum:]\s]/,''). # strip accents
34
+ gsub(/[^[:alnum:]\s]/,''). # strip accents
11
35
  downcase.
12
36
  split(' ').
13
37
  reject { |word| word.size < 2 }
@@ -1,2 +1,4 @@
1
+ require 'mongoid_search/railtie' if defined?(Rails)
1
2
  require 'mongoid_search/util'
3
+ require 'mongoid_search/log'
2
4
  require 'mongoid_search/mongoid_search'
@@ -30,12 +30,24 @@ describe Mongoid::Search do
30
30
  end
31
31
  end
32
32
 
33
+ context "when references are nil" do
34
+ context "when instance is being created" do
35
+ it "should not complain about method missing" do
36
+ lambda { Product.create! }.should_not raise_error
37
+ end
38
+ end
39
+
40
+ subject { Product.create :brand => "Apple", :name => "iPhone" }
41
+
42
+ its(:_keywords) { should == ["apple", "iphone"] }
43
+ end
44
+
33
45
  it "should set the _keywords field for array fields also" do
34
46
  @product.attrs = ['lightweight', 'plastic', :red]
35
47
  @product.save!
36
48
  @product._keywords.should include 'lightweight', 'plastic', 'red'
37
49
  end
38
-
50
+
39
51
  it "should inherit _keywords field and build upon" do
40
52
  variant = Variant.create :brand => "Apple",
41
53
  :name => "iPhone",
@@ -123,10 +135,23 @@ describe Mongoid::Search do
123
135
  it "should search for embedded documents" do
124
136
  Product.search("craddle").size.should == 1
125
137
  end
126
-
138
+
127
139
  it 'should work in a chainable fashion' do
128
140
  @product.category.products.where(:brand => 'Apple').csearch('apple').size.should == 1
129
141
  @product.category.products.csearch('craddle').where(:brand => 'Apple').size.should == 1
130
142
  end
143
+
144
+ it 'should return the classes that include the search module' do
145
+ Mongoid::Search.classes.should == [Product]
146
+ end
147
+
148
+ it 'should have a method to index keywords' do
149
+ @product.index_keywords!.should == true
150
+ end
151
+
152
+ it 'should have a class method to index all documents keywords' do
153
+ Product.index_keywords!.should_not include(false)
154
+ end
155
+
131
156
 
132
157
  end
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,6 @@
1
+ require 'simplecov'
2
+ SimpleCov.start
3
+
1
4
  $LOAD_PATH.unshift(File.dirname(__FILE__))
2
5
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
6
  require 'mongoid'
data/spec/util_spec.rb CHANGED
@@ -3,42 +3,42 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
3
3
 
4
4
  describe Util do
5
5
  it "should return an empty array if no text is passed" do
6
- Util.keywords("", false, "").should == []
6
+ Util.normalize_keywords("", false, "").should == []
7
7
  end
8
8
 
9
9
  it "should return an array of keywords" do
10
- Util.keywords("keyword", false, "").class.should == Array
10
+ Util.normalize_keywords("keyword", false, "").class.should == Array
11
11
  end
12
12
 
13
13
  it "should return an array of strings" do
14
- Util.keywords("keyword", false, "").first.class.should == String
14
+ Util.normalize_keywords("keyword", false, "").first.class.should == String
15
15
  end
16
16
 
17
17
  it "should remove accents from the text passed" do
18
- Util.keywords("café", false, "").should == ["cafe"]
18
+ Util.normalize_keywords("café", false, "").should == ["cafe"]
19
19
  end
20
20
 
21
21
  it "should downcase the text passed" do
22
- Util.keywords("CaFé", false, "").should == ["cafe"]
22
+ Util.normalize_keywords("CaFé", false, "").should == ["cafe"]
23
23
  end
24
24
 
25
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"]
26
+ Util.normalize_keywords("CaFé-express.com delicious;come visit, and 'win' an \"iPad\"", false, "").should == ["cafe", "express", "com", "delicious", "come", "visit", "and", "win", "an", "ipad"]
27
27
  end
28
28
 
29
29
  it "should stem keywords" do
30
- Util.keywords("A runner running and eating", true, "").should == ["runner", "run", "and", "eat"]
30
+ Util.normalize_keywords("A runner running and eating", true, "").should == ["runner", "run", "and", "eat"]
31
31
  end
32
32
 
33
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"]
34
+ Util.normalize_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
35
  end
36
36
 
37
37
  it "should ignore keywords with less than two words" do
38
- Util.keywords("A runner running", false, "").should_not include "a"
38
+ Util.normalize_keywords("A runner running", false, "").should_not include "a"
39
39
  end
40
40
 
41
41
  it "should not ignore numbers" do
42
- Util.keywords("Ford T 1908", false, "").should include "1908"
42
+ Util.normalize_keywords("Ford T 1908", false, "").should include "1908"
43
43
  end
44
44
  end
metadata CHANGED
@@ -1,132 +1,156 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: mongoid_search
3
- version: !ruby/object:Gem::Version
4
- version: 0.2.6
5
- prerelease:
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 2
8
+ - 7
9
+ version: 0.2.7
6
10
  platform: ruby
7
- authors:
11
+ authors:
8
12
  - Mauricio Zaffari
9
13
  autorequire:
10
14
  bindir: bin
11
15
  cert_chain: []
12
- date: 2011-05-31 00:00:00.000000000 -03:00
16
+
17
+ date: 2011-08-10 00:00:00 -03:00
13
18
  default_executable:
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
16
21
  name: mongoid
17
- requirement: &2155959000 !ruby/object:Gem::Requirement
18
- none: false
19
- requirements:
20
- - - ~>
21
- - !ruby/object:Gem::Version
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 2
29
+ - 0
30
+ - 0
22
31
  version: 2.0.0
23
32
  type: :runtime
24
- prerelease: false
25
- version_requirements: *2155959000
26
- - !ruby/object:Gem::Dependency
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
27
35
  name: bson_ext
28
- requirement: &2155958360 !ruby/object:Gem::Requirement
29
- none: false
30
- requirements:
31
- - - ~>
32
- - !ruby/object:Gem::Version
33
- version: '1.2'
34
- type: :runtime
35
36
  prerelease: false
36
- version_requirements: *2155958360
37
- - !ruby/object:Gem::Dependency
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 1
43
+ - 2
44
+ version: "1.2"
45
+ type: :runtime
46
+ version_requirements: *id002
47
+ - !ruby/object:Gem::Dependency
38
48
  name: fast-stemmer
39
- requirement: &2155957680 !ruby/object:Gem::Requirement
40
- none: false
41
- requirements:
49
+ prerelease: false
50
+ requirement: &id003 !ruby/object:Gem::Requirement
51
+ requirements:
42
52
  - - ~>
43
- - !ruby/object:Gem::Version
53
+ - !ruby/object:Gem::Version
54
+ segments:
55
+ - 1
56
+ - 0
57
+ - 0
44
58
  version: 1.0.0
45
59
  type: :runtime
46
- prerelease: false
47
- version_requirements: *2155957680
48
- - !ruby/object:Gem::Dependency
60
+ version_requirements: *id003
61
+ - !ruby/object:Gem::Dependency
49
62
  name: database_cleaner
50
- requirement: &2155957100 !ruby/object:Gem::Requirement
51
- none: false
52
- requirements:
63
+ prerelease: false
64
+ requirement: &id004 !ruby/object:Gem::Requirement
65
+ requirements:
53
66
  - - ~>
54
- - !ruby/object:Gem::Version
67
+ - !ruby/object:Gem::Version
68
+ segments:
69
+ - 0
70
+ - 6
71
+ - 4
55
72
  version: 0.6.4
56
73
  type: :development
57
- prerelease: false
58
- version_requirements: *2155957100
59
- - !ruby/object:Gem::Dependency
74
+ version_requirements: *id004
75
+ - !ruby/object:Gem::Dependency
60
76
  name: rake
61
- requirement: &2155956180 !ruby/object:Gem::Requirement
62
- none: false
63
- requirements:
77
+ prerelease: false
78
+ requirement: &id005 !ruby/object:Gem::Requirement
79
+ requirements:
64
80
  - - ~>
65
- - !ruby/object:Gem::Version
81
+ - !ruby/object:Gem::Version
82
+ segments:
83
+ - 0
84
+ - 8
85
+ - 7
66
86
  version: 0.8.7
67
87
  type: :development
68
- prerelease: false
69
- version_requirements: *2155956180
70
- - !ruby/object:Gem::Dependency
88
+ version_requirements: *id005
89
+ - !ruby/object:Gem::Dependency
71
90
  name: rspec
72
- requirement: &2155955460 !ruby/object:Gem::Requirement
73
- none: false
74
- requirements:
91
+ prerelease: false
92
+ requirement: &id006 !ruby/object:Gem::Requirement
93
+ requirements:
75
94
  - - ~>
76
- - !ruby/object:Gem::Version
77
- version: '2.4'
95
+ - !ruby/object:Gem::Version
96
+ segments:
97
+ - 2
98
+ - 4
99
+ version: "2.4"
78
100
  type: :development
79
- prerelease: false
80
- version_requirements: *2155955460
101
+ version_requirements: *id006
81
102
  description: Simple full text search implementation.
82
- email:
103
+ email:
83
104
  - mauricio@papodenerd.net
84
105
  executables: []
106
+
85
107
  extensions: []
108
+
86
109
  extra_rdoc_files: []
87
- files:
110
+
111
+ files:
112
+ - lib/mongoid_search/log.rb
88
113
  - lib/mongoid_search/mongoid_search.rb
114
+ - lib/mongoid_search/railtie.rb
89
115
  - lib/mongoid_search/util.rb
90
116
  - lib/mongoid_search.rb
91
117
  - LICENSE
92
118
  - README.md
93
119
  - Rakefile
94
120
  - VERSION
95
- - spec/config/ignorelist.yml
96
- - spec/models/category.rb
97
- - spec/models/product.rb
98
- - spec/models/subproduct.rb
99
- - spec/models/tag.rb
100
- - spec/models/variant.rb
101
- - spec/mongoid_search_spec.rb
102
- - spec/spec_helper.rb
103
- - spec/util_spec.rb
104
121
  has_rdoc: true
105
122
  homepage: http://www.papodenerd.net/mongoid-search-full-text-search-for-your-mongoid-models/
106
123
  licenses: []
124
+
107
125
  post_install_message:
108
126
  rdoc_options: []
109
- require_paths:
127
+
128
+ require_paths:
110
129
  - lib
111
- required_ruby_version: !ruby/object:Gem::Requirement
112
- none: false
113
- requirements:
114
- - - ! '>='
115
- - !ruby/object:Gem::Version
116
- version: '0'
117
- required_rubygems_version: !ruby/object:Gem::Requirement
118
- none: false
119
- requirements:
120
- - - ! '>='
121
- - !ruby/object:Gem::Version
130
+ required_ruby_version: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ segments:
135
+ - 0
136
+ version: "0"
137
+ required_rubygems_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ segments:
142
+ - 1
143
+ - 3
144
+ - 6
122
145
  version: 1.3.6
123
146
  requirements: []
147
+
124
148
  rubyforge_project:
125
- rubygems_version: 1.6.2
149
+ rubygems_version: 1.3.6
126
150
  signing_key:
127
151
  specification_version: 3
128
152
  summary: Search implementation for Mongoid ORM
129
- test_files:
153
+ test_files:
130
154
  - spec/config/ignorelist.yml
131
155
  - spec/models/category.rb
132
156
  - spec/models/product.rb