mongoid_search 0.3.2 → 0.4.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.
@@ -1,10 +1,7 @@
1
- require 'mongoid_search'
2
- require 'rails'
3
-
4
1
  module Mongoid::Search
5
2
  class Railtie < Rails::Railtie
6
3
  rake_tasks do
7
- Dir[File.join(File.dirname(__FILE__), '../../tasks/*.rake')].each { |f| load f }
4
+ Dir[File.join(File.dirname(__FILE__), 'tasks/*.rake')].each { |f| load f }
8
5
  end
9
6
  end
10
- end
7
+ end
@@ -0,0 +1,16 @@
1
+ namespace :mongoid_search do
2
+ desc 'Goes through all documents with search enabled and indexes the keywords.'
3
+ task index: :environment do
4
+ ::Rails.application.eager_load!
5
+ if Mongoid::Search.classes.blank?
6
+ Mongoid::Search::Log.log "No model to index keywords.\n"
7
+ else
8
+ Mongoid::Search.classes.each do |klass|
9
+ Mongoid::Search::Log.silent = ENV['SILENT']
10
+ Mongoid::Search::Log.log "\nIndexing documents for #{klass.name}:\n"
11
+ klass.index_keywords!
12
+ end
13
+ Mongoid::Search::Log.log "\n\nDone.\n"
14
+ end
15
+ end
16
+ end
@@ -1,28 +1,28 @@
1
- # encoding: utf-8
1
+
2
2
  module Mongoid::Search::Util
3
3
  def self.keywords(klass, fields)
4
4
  if fields.is_a?(Array)
5
5
  fields.map do |field|
6
- self.keywords(klass, field)
6
+ keywords(klass, field)
7
7
  end
8
8
  elsif fields.is_a?(Hash)
9
9
  fields.keys.map do |field|
10
10
  attribute = klass.send(field)
11
11
  unless attribute.blank?
12
12
  if attribute.is_a?(Array)
13
- attribute.map{ |a| self.keywords(a, fields[field]) }
13
+ attribute.map { |a| keywords(a, fields[field]) }
14
14
  else
15
- self.keywords(attribute, fields[field])
15
+ keywords(attribute, fields[field])
16
16
  end
17
17
  end
18
18
  end
19
19
  else
20
- value = if klass.respond_to?(fields.to_s + "_translations")
21
- klass.send(fields.to_s + "_translations").values
20
+ value = if klass.respond_to?(fields.to_s + '_translations')
21
+ klass.send(fields.to_s + '_translations').values
22
22
  elsif klass.respond_to?(fields)
23
23
  klass.send(fields)
24
24
  else
25
- value = klass[fields];
25
+ value = klass[fields]
26
26
  end
27
27
  value = value.join(' ') if value.respond_to?(:join)
28
28
  normalize_keywords(value) if value
@@ -34,21 +34,22 @@ module Mongoid::Search::Util
34
34
  ignore_list = Mongoid::Search.ignore_list
35
35
  stem_keywords = Mongoid::Search.stem_keywords
36
36
  stem_proc = Mongoid::Search.stem_proc
37
+ strip_symbols = Mongoid::Search.strip_symbols
38
+ strip_accents = Mongoid::Search.strip_accents
37
39
 
38
40
  return [] if text.blank?
39
- text = text.to_s.
40
- mb_chars.
41
- normalize(:kd).
42
- downcase.
43
- to_s.
44
- gsub(/[._:;'"`,?|+={}()!@#%^&*<>~\$\-\\\/\[\]]/, ' '). # strip punctuation
45
- gsub(/[^[:alnum:]\s]/,''). # strip accents
46
- gsub(/[#{ligatures.keys.join("")}]/) {|c| ligatures[c]}.
47
- split(' ').
48
- reject { |word| word.size < Mongoid::Search.minimum_word_size }
41
+ text = text.to_s
42
+ .mb_chars
43
+ .unicode_normalize(:nfkd)
44
+ .downcase
45
+ .to_s
46
+ .gsub(strip_symbols, ' ') # strip symbols
47
+ .gsub(strip_accents, '') # strip accents
48
+ .gsub(/[#{ligatures.keys.join("")}]/) { |c| ligatures[c] }
49
+ .split(' ')
50
+ .reject { |word| word.size < Mongoid::Search.minimum_word_size }
49
51
  text = text.reject { |word| ignore_list.include?(word) } unless ignore_list.blank?
50
52
  text = text.map(&stem_proc) if stem_keywords
51
53
  text
52
54
  end
53
-
54
55
  end
@@ -1,5 +1,7 @@
1
1
  class Category
2
2
  include Mongoid::Document
3
+ include Mongoid::Attributes::Dynamic if ::Mongoid::VERSION >= '4'
4
+
3
5
  field :name, localize: true
4
6
  field :description
5
7
 
@@ -1,15 +1,24 @@
1
1
  class Product
2
2
  include Mongoid::Document
3
3
  include Mongoid::Search
4
+ include Mongoid::Attributes::Dynamic if ::Mongoid::VERSION >= '4'
5
+
4
6
  field :brand
5
7
  field :name
6
- field :attrs, :type => Array
7
- field :info, :type => Hash
8
+ field :unit
9
+ field :measures, type: Array
10
+ field :attrs, type: Array
11
+ field :info, type: Hash
8
12
 
9
- has_many :tags
10
- belongs_to :category
13
+ has_many :tags
14
+ if Mongoid::Compatibility::Version.mongoid6_or_newer?
15
+ belongs_to :category, required: false
16
+ else
17
+ belongs_to :category
18
+ end
11
19
  embeds_many :subproducts
12
20
 
13
- search_in :brand, :name, :outlet, :attrs, :tags => :name, :category => [:name, :description],
14
- :subproducts => [:brand, :name], :info => [ :summary, :description ]
21
+ search_in :brand, :name, :outlet, :attrs, tags: :name, category: %i[name description],
22
+ subproducts: %i[brand name], info: %i[summary description]
23
+ search_in :unit, :measures, index: :_unit_keywords
15
24
  end
@@ -1,8 +1,9 @@
1
1
  class Subproduct
2
2
  include Mongoid::Document
3
+ include Mongoid::Attributes::Dynamic if ::Mongoid::VERSION >= '4'
3
4
 
4
5
  field :brand
5
6
  field :name
6
7
 
7
- belongs_to :product, :inverse_of => :subproducts
8
+ embedded_in :product, inverse_of: :subproducts
8
9
  end
@@ -1,14 +1,15 @@
1
1
  class Tag
2
2
  include Mongoid::Document
3
3
  include Mongoid::Search
4
+ include Mongoid::Attributes::Dynamic if ::Mongoid::VERSION >= '4'
4
5
 
5
6
  field :name
6
7
 
7
8
  belongs_to :product
8
9
 
9
10
  def title
10
- self.name
11
+ name
11
12
  end
12
13
 
13
- search_in :title, :product => [:name, { :info => [ :summary, :description ], :category => [:name, :description]}]
14
+ search_in :title, product: [:name, { info: %i[summary description], category: %i[name description] }]
14
15
  end
@@ -1,5 +1,7 @@
1
- autoload :Product, "models/product.rb"
1
+ autoload :Product, 'models/product.rb'
2
2
  class Variant < Product
3
3
  field :color
4
+ field :size
4
5
  search_in :color
6
+ search_in :size, index: :_unit_keywords
5
7
  end
@@ -1,11 +1,10 @@
1
- # encoding: utf-8
2
-
3
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
4
2
 
5
3
  describe Mongoid::Search do
6
-
7
4
  before(:all) do
8
5
  @default_proc = Mongoid::Search.stem_proc
6
+ @default_strip_symbols = Mongoid::Search.strip_symbols
7
+ @default_strip_accents = Mongoid::Search.strip_accents
9
8
  end
10
9
 
11
10
  after(:all) do
@@ -17,257 +16,356 @@ describe Mongoid::Search do
17
16
  Mongoid::Search.stem_keywords = false
18
17
  Mongoid::Search.ignore_list = nil
19
18
  Mongoid::Search.stem_proc = @default_proc
20
- @product = Product.create :brand => "Apple",
21
- :name => "iPhone",
22
- :tags => (@tags = ["Amazing", "Awesome", "Olé"].map { |tag| Tag.new(:name => tag) }),
23
- :category => Category.new(:name => "Mobile", :description => "Reviews"),
24
- :subproducts => [Subproduct.new(:brand => "Apple", :name => "Craddle")],
25
- :info => { :summary => "Info-summary",
26
- :description => "Info-description"}
27
- end
28
-
29
- describe "Serialized hash fields" do
30
- context "when the hash is populated" do
31
- it "should return the product" do
32
- Product.full_text_search("Info-summary").first.should eq @product
33
- Product.full_text_search("Info-description").first.should eq @product
19
+ @product = Product.create brand: 'Apple',
20
+ name: 'iPhone',
21
+ unit: 'mobile olé awesome',
22
+ tags: (@tags = %w[Amazing Awesome Olé].map { |tag| Tag.new(name: tag) }),
23
+ category: Category.new(name: 'Mobile', description: 'Reviews'),
24
+ subproducts: [Subproduct.new(brand: 'Apple', name: 'Craddle')],
25
+ info: { summary: 'Info-summary',
26
+ description: 'Info-description' }
27
+ end
28
+
29
+ describe 'Serialized hash fields' do
30
+ context 'when the hash is populated' do
31
+ it 'should return the product' do
32
+ expect(Product.full_text_search('Info-summary').first).to eq @product
33
+ expect(Product.full_text_search('Info-description').first).to eq @product
34
34
  end
35
35
  end
36
36
 
37
- context "when the hash is empty" do
37
+ context 'when the hash is empty' do
38
38
  before(:each) do
39
39
  @product.info = nil
40
40
  @product.save
41
41
  end
42
42
 
43
- it "should not return the product" do
44
- Product.full_text_search("Info-description").size.should eq 0
45
- Product.full_text_search("Info-summary").size.should eq 0
43
+ it 'should not return the product' do
44
+ expect(Product.full_text_search('Info-description').size).to eq 0
45
+ expect(Product.full_text_search('Info-summary').size).to eq 0
46
46
  end
47
47
  end
48
48
  end
49
49
 
50
- context "utf-8 characters" do
50
+ context 'utf-8 characters' do
51
51
  before do
52
52
  Mongoid::Search.stem_keywords = false
53
53
  Mongoid::Search.ignore_list = nil
54
- @product = Product.create :brand => "Эльбрус",
55
- :name => "Процессор",
56
- :tags => ["Amazing", "Awesome", "Olé"].map { |tag| Tag.new(:name => tag) },
57
- :category => Category.new(:name => "процессоры"),
58
- :subproducts => []
54
+ @product = Product.create brand: 'Эльбрус',
55
+ name: 'Процессор',
56
+ unit: 'kílográm Olé',
57
+ tags: %w[Amazing Awesome Olé].map { |tag| Tag.new(name: tag) },
58
+ category: Category.new(name: 'процессоры'),
59
+ subproducts: []
59
60
  end
60
61
 
61
- it "should leave utf8 characters" do
62
- @product._keywords.should == ["amazing", "awesome", "ole", "процессор", "процессоры", "эльбрус"]
62
+ it 'should leave utf8 characters' do
63
+ expect(@product._keywords).to eq %w[amazing awesome ole процессор процессоры эльбрус]
64
+ expect(@product._unit_keywords).to eq %w[kilogram ole]
63
65
  end
64
66
 
65
67
  it "should return results in search when case doesn't match" do
66
- Product.full_text_search("ЭЛЬБРУС").size.should == 1
68
+ expect(Product.full_text_search('ЭЛЬБРУС').size).to eq 1
69
+ expect(Product.full_text_search('KILOGRAM', index: :_unit_keywords).size).to eq 1
67
70
  end
68
71
  end
69
72
 
70
- context "when references are nil" do
71
- context "when instance is being created" do
72
- it "should not complain about method missing" do
73
- lambda { Product.create! }.should_not raise_error
73
+ context 'when references are nil' do
74
+ context 'when instance is being created' do
75
+ it 'should not complain about method missing' do
76
+ expect { Product.create! }.not_to raise_error
74
77
  end
75
78
  end
76
79
 
77
- subject { Product.create :brand => "Apple", :name => "iPhone" }
78
-
79
- its(:_keywords) { should == ["apple", "iphone"] }
80
+ it 'should validate keywords' do
81
+ product = Product.create brand: 'Apple', name: 'iPhone', unit: 'box'
82
+ expect(product._keywords).to eq(%w[apple iphone])
83
+ expect(product._unit_keywords).to eq(%w[box])
84
+ end
80
85
  end
81
86
 
82
-
83
- it "should set the _keywords field for array fields also" do
87
+ it 'should set the _keywords field for array fields also' do
84
88
  @product.attrs = ['lightweight', 'plastic', :red]
89
+ @product.measures = ['box', 'bunch', :bag]
85
90
  @product.save!
86
- @product._keywords.should include 'lightweight', 'plastic', 'red'
91
+ expect(@product._keywords).to include 'lightweight', 'plastic', 'red'
92
+ expect(@product._unit_keywords).to include 'box', 'bunch', 'bag'
87
93
  end
88
94
 
89
- it "should inherit _keywords field and build upon" do
90
- variant = Variant.create :brand => "Apple",
91
- :name => "iPhone",
92
- :tags => ["Amazing", "Awesome", "Olé"].map { |tag| Tag.new(:name => tag) },
93
- :category => Category.new(:name => "Mobile"),
94
- :subproducts => [Subproduct.new(:brand => "Apple", :name => "Craddle")],
95
- :color => :white
96
- variant._keywords.should include 'white'
97
- Variant.full_text_search(:name => 'Apple', :color => :white).should eq [variant]
95
+ it 'should inherit _keywords field and build upon' do
96
+ variant = Variant.create brand: 'Apple',
97
+ name: 'iPhone',
98
+ tags: %w[Amazing Awesome Olé].map { |tag| Tag.new(name: tag) },
99
+ category: Category.new(name: 'Mobile'),
100
+ subproducts: [Subproduct.new(brand: 'Apple', name: 'Craddle')],
101
+ color: :white,
102
+ size: :big
103
+ expect(variant._keywords).to include 'white'
104
+ expect(variant._unit_keywords).to include 'big'
105
+ expect(Variant.full_text_search(name: 'Apple', color: :white)).to eq [variant]
106
+ expect(Variant.full_text_search({ size: 'big' }, index: :_unit_keywords)).to eq [variant]
98
107
  end
99
108
 
100
- it "should expand the ligature to ease searching" do
109
+ it 'should expand the ligature to ease searching' do
101
110
  # ref: http://en.wikipedia.org/wiki/Typographic_ligature, only for french right now. Rules for other languages are not know
102
- variant1 = Variant.create :tags => ["œuvre"].map {|tag| Tag.new(:name => tag)}
103
- variant2 = Variant.create :tags => ["æquo"].map {|tag| Tag.new(:name => tag)}
111
+ variant1 = Variant.create tags: ['œuvre'].map { |tag| Tag.new(name: tag) }
112
+ variant2 = Variant.create tags: ['æquo'].map { |tag| Tag.new(name: tag) }
113
+ variant3 = Variant.create measures: ['ꜵquo'].map { |measure| measure }
104
114
 
105
- Variant.full_text_search("œuvre").should eq [variant1]
106
- Variant.full_text_search("oeuvre").should eq [variant1]
107
- Variant.full_text_search("æquo").should eq [variant2]
108
- Variant.full_text_search("aequo").should eq [variant2]
115
+ expect(Variant.full_text_search('œuvre')).to eq [variant1]
116
+ expect(Variant.full_text_search('oeuvre')).to eq [variant1]
117
+ expect(Variant.full_text_search('æquo')).to eq [variant2]
118
+ expect(Variant.full_text_search('aequo')).to eq [variant2]
119
+ expect(Variant.full_text_search('aoquo', index: :_unit_keywords)).to eq [variant3]
120
+ expect(Variant.full_text_search('ꜵquo', index: :_unit_keywords)).to eq [variant3]
109
121
  end
110
122
 
111
- it "should set the _keywords field with stemmed words if stem is enabled" do
123
+ it 'should set the keywords fields with stemmed words if stem is enabled' do
112
124
  Mongoid::Search.stem_keywords = true
113
125
  @product.save!
114
- @product._keywords.sort.should == ["amaz", "appl", "awesom", "craddl", "iphon", "mobil", "review", "ol", "info", "descript", "summari"].sort
126
+ expect(@product._keywords.sort).to eq %w[amaz appl awesom craddl iphon mobil review ol info descript summari].sort
127
+ expect(@product._unit_keywords.sort).to eq %w[mobil awesom ol].sort
115
128
  end
116
129
 
117
- it "should set the _keywords field with custom stemmed words if stem is enabled with a custom lambda" do
130
+ it 'should set the keywords fields with custom stemmed words if stem is enabled with a custom lambda' do
118
131
  Mongoid::Search.stem_keywords = true
119
- Mongoid::Search.stem_proc = Proc.new { |word| word.upcase }
132
+ Mongoid::Search.stem_proc = proc { |word| word.upcase }
120
133
  @product.save!
121
- @product._keywords.sort.should == ["AMAZING", "APPLE", "AWESOME", "CRADDLE", "DESCRIPTION", "INFO", "IPHONE", "MOBILE", "OLE", "REVIEWS", "SUMMARY"]
134
+ expect(@product._keywords.sort).to eq %w[AMAZING APPLE AWESOME CRADDLE DESCRIPTION INFO IPHONE MOBILE OLE REVIEWS SUMMARY]
135
+ expect(@product._unit_keywords.sort).to eq %w[AWESOME MOBILE OLE]
122
136
  end
123
137
 
124
- it "should ignore keywords in an ignore list" do
125
- Mongoid::Search.ignore_list = YAML.load(File.open(File.dirname(__FILE__) + '/config/ignorelist.yml'))["ignorelist"]
138
+ it 'should ignore keywords in an ignore list' do
139
+ Mongoid::Search.ignore_list = YAML.safe_load(File.open(File.dirname(__FILE__) + '/config/ignorelist.yml'))['ignorelist']
126
140
  @product.save!
127
- @product._keywords.sort.should == ["apple", "craddle", "iphone", "mobile", "reviews", "ole", "info", "description", "summary"].sort
141
+ expect(@product._keywords.sort).to eq %w[apple craddle iphone mobile reviews ole info description summary].sort
142
+ expect(@product._unit_keywords.sort).to eq %w[mobile ole].sort
128
143
  end
129
144
 
130
- it "should incorporate numbers as keywords" do
131
- @product = Product.create :brand => "Ford",
132
- :name => "T 1908",
133
- :tags => ["Amazing", "First", "Car"].map { |tag| Tag.new(:name => tag) },
134
- :category => Category.new(:name => "Vehicle")
145
+ it 'should incorporate numbers as keywords' do
146
+ @product = Product.create brand: 'Ford',
147
+ name: 'T 1908',
148
+ tags: %w[Amazing First Car].map { |tag| Tag.new(name: tag) },
149
+ category: Category.new(name: 'Vehicle')
135
150
 
136
- @product.save!
137
- @product._keywords.should == ["1908", "amazing", "car", "first", "ford", "vehicle"]
138
- end
151
+ @product.save!
152
+ expect(@product._keywords).to eq %w[1908 amazing car first ford vehicle]
153
+ end
139
154
 
140
- it "should return results in search" do
141
- Product.full_text_search("apple").size.should == 1
155
+ it 'should return results in search' do
156
+ expect(Product.full_text_search('apple').size).to eq 1
142
157
  end
143
158
 
144
- it "should return results in search for dynamic attribute" do
145
- @product[:outlet] = "online shop"
159
+ it 'should return results in search for dynamic attribute' do
160
+ @product[:outlet] = 'online shop'
146
161
  @product.save!
147
- Product.full_text_search("online").size.should == 1
162
+ expect(Product.full_text_search('online').size).to eq 1
148
163
  end
149
164
 
150
- it "should return results in search even searching a accented word" do
151
- Product.full_text_search("Ole").size.should == 1
152
- Product.full_text_search("Olé").size.should == 1
165
+ it 'should return results in search even searching a accented word' do
166
+ expect(Product.full_text_search('Ole').size).to eq 1
167
+ expect(Product.full_text_search('Olé').size).to eq 1
153
168
  end
154
169
 
155
170
  it "should return results in search even if the case doesn't match" do
156
- Product.full_text_search("oLe").size.should == 1
171
+ expect(Product.full_text_search('oLe').size).to eq 1
157
172
  end
158
173
 
159
- it "should return results in search with a partial word by default" do
160
- Product.full_text_search("iph").size.should == 1
174
+ it 'should return results in search with a partial word by default' do
175
+ expect(Product.full_text_search('iph').size).to eq 1
161
176
  end
162
177
 
163
- it "should return results for any matching word with default search" do
164
- Product.full_text_search("apple motorola").size.should == 1
178
+ it 'should return results for any matching word with default search' do
179
+ expect(Product.full_text_search('apple motorola').size).to eq 1
165
180
  end
166
181
 
167
- it "should not return results when all words do not match, if using :match => :all" do
182
+ it 'should not return results when all words do not match, if using :match => :all' do
168
183
  Mongoid::Search.match = :all
169
- Product.full_text_search("apple motorola").size.should == 0
184
+ expect(Product.full_text_search('apple motorola').size).to eq 0
170
185
  end
171
186
 
172
- it "should return results for any matching word, using :match => :all, passing :match => :any to .full_text_search" do
187
+ it 'should return results for any matching word, using :match => :all, passing :match => :any to .full_text_search' do
173
188
  Mongoid::Search.match = :all
174
- Product.full_text_search("apple motorola", :match => :any).size.should == 1
189
+ expect(Product.full_text_search('apple motorola', match: :any).size).to eq 1
175
190
  end
176
191
 
177
- it "should not return results when all words do not match, passing :match => :all to .full_text_search" do
178
- Product.full_text_search("apple motorola", :match => :all).size.should == 0
192
+ it 'should not return results when all words do not match, passing :match => :all to .full_text_search' do
193
+ expect(Product.full_text_search('apple motorola', match: :all).size).to eq 0
179
194
  end
180
195
 
181
- it "should return no results when a blank search is made" do
196
+ it 'should return no results when a blank search is made' do
182
197
  Mongoid::Search.allow_empty_search = false
183
- Product.full_text_search("").size.should == 0
198
+ expect(Product.full_text_search('').size).to eq 0
184
199
  end
185
200
 
186
- it "should return results when a blank search is made when :allow_empty_search is true" do
201
+ it 'should return results when a blank search is made when :allow_empty_search is true' do
187
202
  Mongoid::Search.allow_empty_search = true
188
- Product.full_text_search("").size.should == 1
203
+ expect(Product.full_text_search('').size).to eq 1
189
204
  end
190
205
 
191
- it "should search for embedded documents" do
192
- Product.full_text_search("craddle").size.should == 1
206
+ it 'should search for embedded documents' do
207
+ expect(Product.full_text_search('craddle').size).to eq 1
193
208
  end
194
209
 
195
- it "should search for reference documents" do
196
- Product.full_text_search("reviews").size.should == 1
210
+ it 'should search for reference documents' do
211
+ expect(Product.full_text_search('reviews').size).to eq 1
197
212
  end
198
213
 
199
214
  it 'should work in a chainable fashion' do
200
- @product.category.products.where(:brand => 'Apple').full_text_search('apple').size.should == 1
201
- @product.category.products.full_text_search('craddle').where(:brand => 'Apple').size.should == 1
215
+ expect(@product.category.products.where(brand: 'Apple').full_text_search('apple').size).to eq 1
216
+ expect(@product.category.products.full_text_search('craddle').where(brand: 'Apple').size).to eq 1
202
217
  end
203
218
 
204
219
  it 'should return the classes that include the search module' do
205
- Mongoid::Search.classes.should == [Product, Tag]
220
+ expect(Mongoid::Search.classes.sort_by(&:name)).to eq [Product, Tag]
206
221
  end
207
222
 
208
223
  it 'should have a method to index keywords' do
209
- @product.index_keywords!.should == true
224
+ expect(@product.index_keywords!).to include(true)
210
225
  end
211
226
 
212
227
  it 'should have a class method to index all documents keywords' do
213
- Product.index_keywords!.should_not include(false)
228
+ expect(Product.index_keywords!).not_to include(false)
214
229
  end
215
230
 
216
- context "when regex search is false" do
231
+ context 'when regex search is false' do
217
232
  before do
218
233
  Mongoid::Search.regex_search = false
219
234
  end
220
235
 
221
- it "should not return results in search with a partial word if not using regex search" do
222
- Product.full_text_search("iph").size.should == 0
236
+ it 'should not return results in search with a partial word if not using regex search' do
237
+ expect(Product.full_text_search('iph').size).to eq 0
223
238
  end
224
239
 
225
- it "should return results in search with a full word if not using regex search" do
226
- Product.full_text_search("iphone").size.should == 1
240
+ it 'should return results in search with a full word if not using regex search' do
241
+ expect(Product.full_text_search('iphone').size).to eq 1
227
242
  end
228
243
  end
229
244
 
230
- context "relevant search" do
245
+ context 'when regex search is true' do
246
+ before do
247
+ Mongoid::Search.regex_search = true
248
+ end
249
+
250
+ after do
251
+ Mongoid::Search.regex_search = false
252
+ end
253
+
254
+ it 'should not return results in search with a partial word if using regex search' do
255
+ expect(Product.full_text_search('iph').size).to eq 1
256
+ end
257
+
258
+ it 'should return results in search with a full word if using regex search' do
259
+ expect(Product.full_text_search('iphone').size).to eq 1
260
+ end
261
+
262
+ context 'when query include special characters that should not be stripped' do
263
+ before do
264
+ Mongoid::Search.strip_symbols = /[\n]/
265
+ Mongoid::Search.strip_accents = /[^\s\p{Graph}]/
266
+ end
267
+
268
+ after do
269
+ Mongoid::Search.strip_symbols = @default_strip_symbols
270
+ Mongoid::Search.strip_accents = @default_strip_accents
271
+ end
272
+
273
+ it 'should escape regex special characters' do
274
+ expect(Product.full_text_search('iphone (steve').size).to eq 1
275
+ end
276
+ end
277
+
278
+ context 'Match partial words on the beginning' do
279
+ before do
280
+ Mongoid::Search.regex = proc { |query| /^#{query}/ }
281
+ end
282
+
283
+ it 'should return results in search which starts with query string' do
284
+ expect(Product.full_text_search('iphone').size).to eq 1
285
+ end
286
+
287
+ it 'should not return results in search which does not start with query string' do
288
+ expect(Product.full_text_search('phone').size).to eq 0
289
+ end
290
+ end
291
+
292
+ context 'Match partial words on the end' do
293
+ before do
294
+ Mongoid::Search.regex = proc { |query| /#{query}$/ }
295
+ end
296
+
297
+ it 'should return results in search which ends with query string' do
298
+ expect(Product.full_text_search('phone').size).to eq 1
299
+ end
300
+
301
+ it 'should not return results in search which does not end with query string' do
302
+ expect(Product.full_text_search('phon').size).to eq 0
303
+ end
304
+ end
305
+ end
306
+
307
+ context 'relevant search' do
231
308
  before do
232
309
  Mongoid::Search.relevant_search = true
233
- @imac = Product.create :name => 'apple imac'
310
+ @imac = Product.create name: 'apple imac'
311
+ end
312
+
313
+ it 'should return results ordered by relevance and with correct ids' do
314
+ expect(Product.full_text_search('apple imac').map(&:_id)).to eq [@imac._id, @product._id]
234
315
  end
235
316
 
236
- it "should return results ordered by relevance and with correct ids" do
237
- Product.full_text_search('apple imac').map(&:_id).should == [@imac._id, @product._id]
317
+ it 'results should be recognized as persisted objects' do
318
+ expect(Product.full_text_search('apple imac').map(&:persisted?)).not_to include false
238
319
  end
239
320
 
240
- it "results should be recognized as persisted objects" do
241
- Product.full_text_search('apple imac').map(&:persisted?).should_not include false
321
+ it 'should include relevance information' do
322
+ expect(Product.full_text_search('apple imac').map(&:relevance)).to eq [2, 1]
242
323
  end
324
+ end
243
325
 
244
- it "should include relevance information" do
245
- Product.full_text_search('apple imac').map(&:relevance).should == [2, 1]
326
+ context 'when using methods for keywords' do
327
+ it 'should set the _keywords from methods' do
328
+ expect(@tags.first._keywords).to include 'amazing'
246
329
  end
247
330
  end
248
331
 
249
- context "when using methods for keywords" do
250
- it "should set the _keywords from methods" do
251
- @tags.first._keywords.should include "amazing"
332
+ context 'when using deeply nested fields for keywords' do
333
+ context 'when explicitly calling set_keywords' do
334
+ it 'should set the _keywords from parent' do
335
+ @tags.first.send(:set_keywords)
336
+ expect(@tags.first._keywords).to eq %w[amazing description info iphone mobile reviews summary]
337
+ end
252
338
  end
253
339
  end
254
340
 
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
341
+ context 'when using localized fields' do
342
+ it 'should set the keywords from all localizations' do
343
+ @product = Product.create brand: 'Ford',
344
+ name: 'T 1908',
345
+ tags: %w[Amazing First Car].map { |tag| Tag.new(name: tag) },
346
+ category: Category.new(name_translations: { en: 'Vehicle', de: 'Fahrzeug' })
347
+ expect(@product._keywords).to include('fahrzeug')
261
348
  end
262
349
  end
263
350
 
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")
351
+ context 'minimum word size' do
352
+ before(:each) do
353
+ Mongoid::Search.minimum_word_size = 3
354
+ end
355
+
356
+ after(:each) do
357
+ Mongoid::Search.minimum_word_size = 2
358
+ end
359
+
360
+ it 'should ignore keywords with length less than minimum word size' do
361
+ @product = Product.create name: 'a'
362
+ expect(@product._keywords.size).to eq 0
363
+
364
+ @product = Product.create name: 'ap'
365
+ expect(@product._keywords.size).to eq 0
366
+
367
+ @product = Product.create name: 'app'
368
+ expect(@product._keywords.size).to eq 1
271
369
  end
272
370
  end
273
371
  end