pg_search 2.1.7 → 2.3.3
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.
- checksums.yaml +4 -4
- data/.codeclimate.yml +1 -0
- data/.editorconfig +10 -0
- data/.github/dependabot.yml +11 -0
- data/.rubocop.yml +89 -7
- data/.travis.yml +11 -19
- data/CHANGELOG.md +38 -14
- data/Gemfile +1 -1
- data/LICENSE +1 -1
- data/README.md +74 -42
- data/lib/pg_search.rb +15 -58
- data/lib/pg_search/document.rb +2 -2
- data/lib/pg_search/features/dmetaphone.rb +4 -6
- data/lib/pg_search/features/trigram.rb +29 -5
- data/lib/pg_search/features/tsearch.rb +13 -12
- data/lib/pg_search/migration/templates/add_pg_search_dmetaphone_support_functions.rb.erb +6 -6
- data/lib/pg_search/migration/templates/create_pg_search_documents.rb.erb +2 -2
- data/lib/pg_search/model.rb +59 -0
- data/lib/pg_search/multisearch.rb +10 -1
- data/lib/pg_search/multisearch/rebuilder.rb +7 -3
- data/lib/pg_search/multisearchable.rb +4 -4
- data/lib/pg_search/scope_options.rb +2 -10
- data/lib/pg_search/tasks.rb +2 -1
- data/lib/pg_search/version.rb +1 -1
- data/pg_search.gemspec +10 -5
- data/spec/.rubocop.yml +2 -2
- data/spec/integration/.rubocop.yml +11 -0
- data/spec/integration/associations_spec.rb +36 -75
- data/spec/integration/deprecation_spec.rb +33 -0
- data/spec/integration/pagination_spec.rb +1 -1
- data/spec/integration/pg_search_spec.rb +199 -188
- data/spec/integration/single_table_inheritance_spec.rb +2 -2
- data/spec/lib/pg_search/configuration/association_spec.rb +10 -8
- data/spec/lib/pg_search/configuration/foreign_column_spec.rb +3 -3
- data/spec/lib/pg_search/features/dmetaphone_spec.rb +2 -2
- data/spec/lib/pg_search/features/trigram_spec.rb +48 -19
- data/spec/lib/pg_search/features/tsearch_spec.rb +16 -10
- data/spec/lib/pg_search/multisearch/rebuilder_spec.rb +124 -76
- data/spec/lib/pg_search/multisearch_spec.rb +49 -30
- data/spec/lib/pg_search/multisearchable_spec.rb +155 -101
- data/spec/lib/pg_search/normalizer_spec.rb +12 -10
- data/spec/lib/pg_search_spec.rb +62 -46
- data/spec/spec_helper.rb +13 -4
- data/spec/support/database.rb +1 -1
- metadata +90 -13
data/lib/pg_search/tasks.rb
CHANGED
@@ -7,11 +7,12 @@ namespace :pg_search do
|
|
7
7
|
namespace :multisearch do
|
8
8
|
desc "Rebuild PgSearch multisearch records for a given model"
|
9
9
|
task :rebuild, %i[model schema] => :environment do |_task, args|
|
10
|
-
raise ArgumentError,
|
10
|
+
raise ArgumentError, <<~MESSAGE unless args.model
|
11
11
|
|
12
12
|
You must pass a model as an argument.
|
13
13
|
Example: rake pg_search:multisearch:rebuild[BlogPost]
|
14
14
|
MESSAGE
|
15
|
+
|
15
16
|
model_class = args.model.classify.constantize
|
16
17
|
connection = PgSearch::Document.connection
|
17
18
|
original_schema_search_path = connection.schema_search_path
|
data/lib/pg_search/version.rb
CHANGED
data/pg_search.gemspec
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
$LOAD_PATH.push File.expand_path('lib', __dir__)
|
4
4
|
require 'pg_search/version'
|
5
5
|
|
6
|
-
Gem::Specification.new do |s|
|
6
|
+
Gem::Specification.new do |s| # rubocop:disable Metrics/BlockLength
|
7
7
|
s.name = 'pg_search'
|
8
8
|
s.version = PgSearch::VERSION
|
9
9
|
s.platform = Gem::Platform::RUBY
|
@@ -18,16 +18,21 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.test_files = `git ls-files -- spec/*`.split("\n")
|
19
19
|
s.require_paths = ['lib']
|
20
20
|
|
21
|
-
s.add_dependency 'activerecord', '>=
|
22
|
-
s.add_dependency 'activesupport', '>=
|
21
|
+
s.add_dependency 'activerecord', '>= 5.2'
|
22
|
+
s.add_dependency 'activesupport', '>= 5.2'
|
23
23
|
|
24
24
|
s.add_development_dependency 'pry'
|
25
25
|
s.add_development_dependency 'rake'
|
26
26
|
s.add_development_dependency 'rspec', '>= 3.3'
|
27
|
-
s.add_development_dependency 'rubocop', '>= 0.
|
27
|
+
s.add_development_dependency 'rubocop', '>= 0.90.0'
|
28
28
|
s.add_development_dependency 'rubocop-performance'
|
29
|
+
s.add_development_dependency 'rubocop-rails'
|
30
|
+
s.add_development_dependency 'rubocop-rake'
|
31
|
+
s.add_development_dependency 'rubocop-rspec'
|
32
|
+
s.add_development_dependency 'rubocop-thread_safety', '>= 0.4.1'
|
29
33
|
s.add_development_dependency 'simplecov'
|
34
|
+
s.add_development_dependency 'warning'
|
30
35
|
s.add_development_dependency 'with_model', '>= 1.2'
|
31
36
|
|
32
|
-
s.required_ruby_version = '>= 2.
|
37
|
+
s.required_ruby_version = '>= 2.5'
|
33
38
|
end
|
data/spec/.rubocop.yml
CHANGED
@@ -2,8 +2,9 @@
|
|
2
2
|
|
3
3
|
require "spec_helper"
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
# rubocop:disable RSpec/NestedGroups
|
6
|
+
describe "a pg_search_scope" do
|
7
|
+
context "when joining to another table" do
|
7
8
|
context "without an :against" do
|
8
9
|
with_model :AssociatedModel do
|
9
10
|
table do |t|
|
@@ -18,7 +19,7 @@ describe PgSearch do
|
|
18
19
|
end
|
19
20
|
|
20
21
|
model do
|
21
|
-
include PgSearch
|
22
|
+
include PgSearch::Model
|
22
23
|
belongs_to :another_model, class_name: 'AssociatedModel'
|
23
24
|
|
24
25
|
pg_search_scope :with_another, associated_against: { another_model: :title }
|
@@ -41,7 +42,7 @@ describe PgSearch do
|
|
41
42
|
end
|
42
43
|
end
|
43
44
|
|
44
|
-
context "
|
45
|
+
context "via a belongs_to association" do
|
45
46
|
with_model :AssociatedModel do
|
46
47
|
table do |t|
|
47
48
|
t.string 'title'
|
@@ -55,7 +56,7 @@ describe PgSearch do
|
|
55
56
|
end
|
56
57
|
|
57
58
|
model do
|
58
|
-
include PgSearch
|
59
|
+
include PgSearch::Model
|
59
60
|
belongs_to :another_model, class_name: 'AssociatedModel'
|
60
61
|
|
61
62
|
pg_search_scope :with_associated, against: :title, associated_against: { another_model: :title }
|
@@ -77,7 +78,7 @@ describe PgSearch do
|
|
77
78
|
end
|
78
79
|
end
|
79
80
|
|
80
|
-
context "
|
81
|
+
context "via a has_many association" do
|
81
82
|
with_model :AssociatedModelWithHasMany do
|
82
83
|
table do |t|
|
83
84
|
t.string 'title'
|
@@ -91,7 +92,7 @@ describe PgSearch do
|
|
91
92
|
end
|
92
93
|
|
93
94
|
model do
|
94
|
-
include PgSearch
|
95
|
+
include PgSearch::Model
|
95
96
|
has_many :other_models, class_name: 'AssociatedModelWithHasMany', foreign_key: 'ModelWithHasMany_id'
|
96
97
|
|
97
98
|
pg_search_scope :with_associated, against: [:title], associated_against: { other_models: :title }
|
@@ -141,8 +142,8 @@ describe PgSearch do
|
|
141
142
|
end
|
142
143
|
end
|
143
144
|
|
144
|
-
context "across multiple associations" do
|
145
|
-
context "on different tables" do
|
145
|
+
context "when across multiple associations" do
|
146
|
+
context "when on different tables" do
|
146
147
|
with_model :FirstAssociatedModel do
|
147
148
|
table do |t|
|
148
149
|
t.string 'title'
|
@@ -163,18 +164,18 @@ describe PgSearch do
|
|
163
164
|
end
|
164
165
|
|
165
166
|
model do
|
166
|
-
include PgSearch
|
167
|
+
include PgSearch::Model
|
167
168
|
|
168
169
|
has_many :models_of_first_type,
|
169
|
-
|
170
|
-
|
170
|
+
class_name: 'FirstAssociatedModel',
|
171
|
+
foreign_key: 'ModelWithManyAssociations_id'
|
171
172
|
|
172
173
|
belongs_to :model_of_second_type,
|
173
|
-
|
174
|
+
class_name: 'SecondAssociatedModel'
|
174
175
|
|
175
176
|
pg_search_scope :with_associated,
|
176
|
-
|
177
|
-
|
177
|
+
against: :title,
|
178
|
+
associated_against: { models_of_first_type: :title, model_of_second_type: :title }
|
178
179
|
end
|
179
180
|
end
|
180
181
|
|
@@ -207,7 +208,7 @@ describe PgSearch do
|
|
207
208
|
end
|
208
209
|
end
|
209
210
|
|
210
|
-
context "on the same table" do
|
211
|
+
context "when on the same table" do
|
211
212
|
with_model :DoublyAssociatedModel do
|
212
213
|
table do |t|
|
213
214
|
t.string 'title'
|
@@ -222,15 +223,15 @@ describe PgSearch do
|
|
222
223
|
end
|
223
224
|
|
224
225
|
model do
|
225
|
-
include PgSearch
|
226
|
+
include PgSearch::Model
|
226
227
|
|
227
228
|
has_many :things,
|
228
|
-
|
229
|
-
|
229
|
+
class_name: 'DoublyAssociatedModel',
|
230
|
+
foreign_key: 'ModelWithDoubleAssociation_id'
|
230
231
|
|
231
232
|
has_many :thingamabobs,
|
232
|
-
|
233
|
-
|
233
|
+
class_name: 'DoublyAssociatedModel',
|
234
|
+
foreign_key: 'ModelWithDoubleAssociation_again_id'
|
234
235
|
|
235
236
|
pg_search_scope :with_associated, against: :title,
|
236
237
|
associated_against: { things: :title, thingamabobs: :title }
|
@@ -268,7 +269,7 @@ describe PgSearch do
|
|
268
269
|
end
|
269
270
|
end
|
270
271
|
|
271
|
-
context "against multiple attributes on one association" do
|
272
|
+
context "when against multiple attributes on one association" do
|
272
273
|
with_model :AssociatedModel do
|
273
274
|
table do |t|
|
274
275
|
t.string 'title'
|
@@ -282,14 +283,14 @@ describe PgSearch do
|
|
282
283
|
end
|
283
284
|
|
284
285
|
model do
|
285
|
-
include PgSearch
|
286
|
+
include PgSearch::Model
|
286
287
|
belongs_to :another_model, class_name: 'AssociatedModel'
|
287
288
|
|
288
289
|
pg_search_scope :with_associated, associated_against: { another_model: %i[title author] }
|
289
290
|
end
|
290
291
|
end
|
291
292
|
|
292
|
-
it "
|
293
|
+
it "joins only once" do
|
293
294
|
included = [
|
294
295
|
ModelWithAssociation.create!(
|
295
296
|
another_model: AssociatedModel.create!(
|
@@ -321,7 +322,7 @@ describe PgSearch do
|
|
321
322
|
end
|
322
323
|
end
|
323
324
|
|
324
|
-
context "against non-text columns" do
|
325
|
+
context "when against non-text columns" do
|
325
326
|
with_model :AssociatedModel do
|
326
327
|
table do |t|
|
327
328
|
t.integer 'number'
|
@@ -335,14 +336,14 @@ describe PgSearch do
|
|
335
336
|
end
|
336
337
|
|
337
338
|
model do
|
338
|
-
include PgSearch
|
339
|
+
include PgSearch::Model
|
339
340
|
belongs_to :another_model, class_name: 'AssociatedModel'
|
340
341
|
|
341
342
|
pg_search_scope :with_associated, associated_against: { another_model: :number }
|
342
343
|
end
|
343
344
|
end
|
344
345
|
|
345
|
-
it "
|
346
|
+
it "casts the columns to text" do
|
346
347
|
associated = AssociatedModel.create!(number: 123)
|
347
348
|
included = [
|
348
349
|
Model.create!(number: 123, another_model: associated),
|
@@ -366,7 +367,7 @@ describe PgSearch do
|
|
366
367
|
|
367
368
|
model do
|
368
369
|
has_many :children
|
369
|
-
include PgSearch
|
370
|
+
include PgSearch::Model
|
370
371
|
pg_search_scope :search_name, against: :name
|
371
372
|
end
|
372
373
|
end
|
@@ -395,7 +396,7 @@ describe PgSearch do
|
|
395
396
|
end
|
396
397
|
end
|
397
398
|
|
398
|
-
context "merging a pg_search_scope into another model's scope" do
|
399
|
+
context "when merging a pg_search_scope into another model's scope" do
|
399
400
|
with_model :ModelWithAssociation do
|
400
401
|
model do
|
401
402
|
has_many :associated_models
|
@@ -409,14 +410,14 @@ describe PgSearch do
|
|
409
410
|
end
|
410
411
|
|
411
412
|
model do
|
412
|
-
include PgSearch
|
413
|
+
include PgSearch::Model
|
413
414
|
belongs_to :model_with_association
|
414
415
|
|
415
416
|
pg_search_scope :search_content, against: :content
|
416
417
|
end
|
417
418
|
end
|
418
419
|
|
419
|
-
it "
|
420
|
+
it "finds records of the other model" do
|
420
421
|
included_associated_1 = AssociatedModel.create(content: "foo bar")
|
421
422
|
included_associated_2 = AssociatedModel.create(content: "foo baz")
|
422
423
|
excluded_associated_1 = AssociatedModel.create(content: "baz quux")
|
@@ -441,7 +442,7 @@ describe PgSearch do
|
|
441
442
|
end
|
442
443
|
end
|
443
444
|
|
444
|
-
context "chained onto a has_many association" do
|
445
|
+
context "when chained onto a has_many association" do
|
445
446
|
with_model :Company do
|
446
447
|
model do
|
447
448
|
has_many :positions
|
@@ -455,54 +456,13 @@ describe PgSearch do
|
|
455
456
|
end
|
456
457
|
|
457
458
|
model do
|
458
|
-
include PgSearch
|
459
|
+
include PgSearch::Model
|
459
460
|
pg_search_scope :search, against: :title, using: %i[tsearch trigram]
|
460
461
|
end
|
461
462
|
end
|
462
463
|
|
463
464
|
# https://github.com/Casecommons/pg_search/issues/106
|
464
|
-
it "
|
465
|
-
company = Company.create!
|
466
|
-
another_company = Company.create!
|
467
|
-
|
468
|
-
included = [
|
469
|
-
Position.create!(company_id: company.id, title: "teller 1")
|
470
|
-
]
|
471
|
-
|
472
|
-
excluded = [
|
473
|
-
Position.create!(company_id: nil, title: "teller 1"),
|
474
|
-
Position.create!(company_id: another_company.id, title: "teller 1"),
|
475
|
-
Position.create!(company_id: company.id, title: "penn 1")
|
476
|
-
]
|
477
|
-
|
478
|
-
results = company.positions.search('teller 1')
|
479
|
-
|
480
|
-
expect(results).to include(*included)
|
481
|
-
expect(results).not_to include(*excluded)
|
482
|
-
end
|
483
|
-
end
|
484
|
-
|
485
|
-
context "chained onto a has_many association" do
|
486
|
-
with_model :Company do
|
487
|
-
model do
|
488
|
-
has_many :positions
|
489
|
-
end
|
490
|
-
end
|
491
|
-
|
492
|
-
with_model :Position do
|
493
|
-
table do |t|
|
494
|
-
t.string :title
|
495
|
-
t.belongs_to :company
|
496
|
-
end
|
497
|
-
|
498
|
-
model do
|
499
|
-
include PgSearch
|
500
|
-
pg_search_scope :search, against: :title, using: %i[tsearch trigram]
|
501
|
-
end
|
502
|
-
end
|
503
|
-
|
504
|
-
# https://github.com/Casecommons/pg_search/issues/106
|
505
|
-
it "should handle numbers in a trigram query properly" do
|
465
|
+
it "handles numbers in a trigram query properly" do
|
506
466
|
company = Company.create!
|
507
467
|
another_company = Company.create!
|
508
468
|
|
@@ -524,3 +484,4 @@ describe PgSearch do
|
|
524
484
|
end
|
525
485
|
end
|
526
486
|
end
|
487
|
+
# rubocop:enable RSpec/NestedGroups
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
describe "Including the deprecated PgSearch module" do
|
6
|
+
with_model :SomeModel do
|
7
|
+
model do
|
8
|
+
ActiveSupport::Deprecation.silence do
|
9
|
+
include PgSearch
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
with_model :AnotherModel
|
15
|
+
|
16
|
+
it "includes PgSearch::Model" do
|
17
|
+
expect(SomeModel.ancestors).to include PgSearch::Model
|
18
|
+
end
|
19
|
+
|
20
|
+
it "prints a deprecation message" do
|
21
|
+
allow(ActiveSupport::Deprecation).to receive(:warn)
|
22
|
+
|
23
|
+
AnotherModel.include(PgSearch)
|
24
|
+
|
25
|
+
expect(ActiveSupport::Deprecation).to have_received(:warn).with(
|
26
|
+
<<~MESSAGE
|
27
|
+
Directly including `PgSearch` into an Active Record model is deprecated and will be removed in pg_search 3.0.
|
28
|
+
|
29
|
+
Please replace `include PgSearch` with `include PgSearch::Model`.
|
30
|
+
MESSAGE
|
31
|
+
)
|
32
|
+
end
|
33
|
+
end
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "spec_helper"
|
4
4
|
|
5
|
+
# rubocop:disable RSpec/NestedGroups
|
5
6
|
describe "an Active Record model which includes PgSearch" do
|
6
7
|
with_model :ModelWithPgSearch do
|
7
8
|
table do |t|
|
@@ -12,7 +13,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
12
13
|
end
|
13
14
|
|
14
15
|
model do
|
15
|
-
include PgSearch
|
16
|
+
include PgSearch::Model
|
16
17
|
belongs_to :parent_model
|
17
18
|
end
|
18
19
|
end
|
@@ -22,7 +23,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
22
23
|
end
|
23
24
|
|
24
25
|
model do
|
25
|
-
include PgSearch
|
26
|
+
include PgSearch::Model
|
26
27
|
has_many :models_with_pg_search
|
27
28
|
scope :active, -> { where(active: true) }
|
28
29
|
end
|
@@ -38,12 +39,12 @@ describe "an Active Record model which includes PgSearch" do
|
|
38
39
|
context "when passed a lambda" do
|
39
40
|
it "builds a dynamic scope" do
|
40
41
|
ModelWithPgSearch.pg_search_scope :search_title_or_content,
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
42
|
+
lambda { |query, pick_content|
|
43
|
+
{
|
44
|
+
query: query.gsub("-remove-", ""),
|
45
|
+
against: pick_content ? :content : :title
|
46
|
+
}
|
47
|
+
}
|
47
48
|
|
48
49
|
included = ModelWithPgSearch.create!(title: 'foo', content: 'bar')
|
49
50
|
excluded = ModelWithPgSearch.create!(title: 'bar', content: 'foo')
|
@@ -56,18 +57,18 @@ describe "an Active Record model which includes PgSearch" do
|
|
56
57
|
context "when an unknown option is passed in" do
|
57
58
|
it "raises an exception when invoked" do
|
58
59
|
ModelWithPgSearch.pg_search_scope :with_unknown_option,
|
59
|
-
|
60
|
-
|
60
|
+
against: :content,
|
61
|
+
foo: :bar
|
61
62
|
|
62
63
|
expect {
|
63
64
|
ModelWithPgSearch.with_unknown_option("foo")
|
64
65
|
}.to raise_error(ArgumentError, /foo/)
|
65
66
|
end
|
66
67
|
|
67
|
-
context "
|
68
|
+
context "with a lambda" do
|
68
69
|
it "raises an exception when invoked" do
|
69
70
|
ModelWithPgSearch.pg_search_scope :with_unknown_option,
|
70
|
-
|
71
|
+
->(*) { { against: :content, foo: :bar } }
|
71
72
|
|
72
73
|
expect {
|
73
74
|
ModelWithPgSearch.with_unknown_option("foo")
|
@@ -79,18 +80,18 @@ describe "an Active Record model which includes PgSearch" do
|
|
79
80
|
context "when an unknown :using is passed" do
|
80
81
|
it "raises an exception when invoked" do
|
81
82
|
ModelWithPgSearch.pg_search_scope :with_unknown_using,
|
82
|
-
|
83
|
-
|
83
|
+
against: :content,
|
84
|
+
using: :foo
|
84
85
|
|
85
86
|
expect {
|
86
87
|
ModelWithPgSearch.with_unknown_using("foo")
|
87
88
|
}.to raise_error(ArgumentError, /foo/)
|
88
89
|
end
|
89
90
|
|
90
|
-
context "
|
91
|
+
context "with a lambda" do
|
91
92
|
it "raises an exception when invoked" do
|
92
93
|
ModelWithPgSearch.pg_search_scope :with_unknown_using,
|
93
|
-
|
94
|
+
->(*) { { against: :content, using: :foo } }
|
94
95
|
|
95
96
|
expect {
|
96
97
|
ModelWithPgSearch.with_unknown_using("foo")
|
@@ -102,18 +103,18 @@ describe "an Active Record model which includes PgSearch" do
|
|
102
103
|
context "when an unknown :ignoring is passed" do
|
103
104
|
it "raises an exception when invoked" do
|
104
105
|
ModelWithPgSearch.pg_search_scope :with_unknown_ignoring,
|
105
|
-
|
106
|
-
|
106
|
+
against: :content,
|
107
|
+
ignoring: :foo
|
107
108
|
|
108
109
|
expect {
|
109
110
|
ModelWithPgSearch.with_unknown_ignoring("foo")
|
110
111
|
}.to raise_error(ArgumentError, /ignoring.*foo/)
|
111
112
|
end
|
112
113
|
|
113
|
-
context "
|
114
|
+
context "with a lambda" do
|
114
115
|
it "raises an exception when invoked" do
|
115
116
|
ModelWithPgSearch.pg_search_scope :with_unknown_ignoring,
|
116
|
-
|
117
|
+
->(*) { { against: :content, ignoring: :foo } }
|
117
118
|
|
118
119
|
expect {
|
119
120
|
ModelWithPgSearch.with_unknown_ignoring("foo")
|
@@ -130,7 +131,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
130
131
|
}.to raise_error(ArgumentError, /against/)
|
131
132
|
end
|
132
133
|
|
133
|
-
context "
|
134
|
+
context "with a lambda" do
|
134
135
|
it "raises an exception when invoked" do
|
135
136
|
ModelWithPgSearch.pg_search_scope :with_unknown_ignoring, ->(*) { {} }
|
136
137
|
|
@@ -144,7 +145,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
144
145
|
end
|
145
146
|
|
146
147
|
describe "a search scope" do
|
147
|
-
context "against a single column" do
|
148
|
+
context "when against a single column" do
|
148
149
|
before do
|
149
150
|
ModelWithPgSearch.pg_search_scope :search_content, against: :content
|
150
151
|
end
|
@@ -157,7 +158,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
157
158
|
results = ModelWithPgSearch.select('id, title').search_content('foo')
|
158
159
|
|
159
160
|
expect(results).to include(included)
|
160
|
-
expect(results).
|
161
|
+
expect(results).not_to include(excluded)
|
161
162
|
|
162
163
|
expect(results.first.attributes.key?('content')).to eq false
|
163
164
|
|
@@ -174,7 +175,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
174
175
|
results = ModelWithPgSearch.search_content('foo').select('id, title')
|
175
176
|
|
176
177
|
expect(results).to include(included)
|
177
|
-
expect(results).
|
178
|
+
expect(results).not_to include(excluded)
|
178
179
|
|
179
180
|
expect(results.first.attributes.key?('content')).to eq false
|
180
181
|
|
@@ -191,7 +192,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
191
192
|
results = ModelWithPgSearch.select('id').search_content('foo').select('title')
|
192
193
|
|
193
194
|
expect(results).to include(included)
|
194
|
-
expect(results).
|
195
|
+
expect(results).not_to include(excluded)
|
195
196
|
|
196
197
|
expect(results.first.attributes.key?('content')).to eq false
|
197
198
|
|
@@ -200,7 +201,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
200
201
|
end
|
201
202
|
end
|
202
203
|
|
203
|
-
context "chained to a cross-table scope" do
|
204
|
+
context "when chained to a cross-table scope" do
|
204
205
|
with_model :House do
|
205
206
|
table do |t|
|
206
207
|
t.references :person
|
@@ -208,7 +209,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
208
209
|
end
|
209
210
|
|
210
211
|
model do
|
211
|
-
include PgSearch
|
212
|
+
include PgSearch::Model
|
212
213
|
belongs_to :person
|
213
214
|
pg_search_scope :search_city, against: [:city]
|
214
215
|
end
|
@@ -220,7 +221,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
220
221
|
end
|
221
222
|
|
222
223
|
model do
|
223
|
-
include PgSearch
|
224
|
+
include PgSearch::Model
|
224
225
|
has_many :houses
|
225
226
|
pg_search_scope :named, against: [:name]
|
226
227
|
scope :with_house_in_city, lambda { |city|
|
@@ -270,7 +271,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
270
271
|
it "does not raise an exception" do
|
271
272
|
relation = Person.named('foo').house_search_city('bar')
|
272
273
|
|
273
|
-
expect { relation.to_a }.
|
274
|
+
expect { relation.to_a }.not_to raise_error
|
274
275
|
end
|
275
276
|
end
|
276
277
|
end
|
@@ -283,7 +284,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
283
284
|
it "does not raise an exception" do
|
284
285
|
relation = ModelWithPgSearch.search_content('foo').search_title('bar')
|
285
286
|
|
286
|
-
expect { relation.to_a }.
|
287
|
+
expect { relation.to_a }.not_to raise_error
|
287
288
|
end
|
288
289
|
end
|
289
290
|
|
@@ -451,7 +452,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
451
452
|
|
452
453
|
it "accepts non-string queries and calls #to_s on them" do
|
453
454
|
foo = ModelWithPgSearch.create!(content: "foo")
|
454
|
-
not_a_string =
|
455
|
+
not_a_string = instance_double("Object", to_s: "foo")
|
455
456
|
expect(ModelWithPgSearch.search_content(not_a_string)).to eq([foo])
|
456
457
|
end
|
457
458
|
|
@@ -462,12 +463,12 @@ describe "an Active Record model which includes PgSearch" do
|
|
462
463
|
end
|
463
464
|
|
464
465
|
model do
|
465
|
-
include PgSearch
|
466
|
+
include PgSearch::Model
|
466
467
|
|
467
468
|
# WARNING: searching timestamps is not something PostgreSQL
|
468
469
|
# full-text search is good at. Use at your own risk.
|
469
470
|
pg_search_scope :search_timestamps,
|
470
|
-
|
471
|
+
against: %i[created_at updated_at]
|
471
472
|
end
|
472
473
|
end
|
473
474
|
|
@@ -481,7 +482,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
481
482
|
end
|
482
483
|
end
|
483
484
|
|
484
|
-
context "against multiple columns" do
|
485
|
+
context "when against multiple columns" do
|
485
486
|
before do
|
486
487
|
ModelWithPgSearch.pg_search_scope :search_title_and_content, against: %i[title content]
|
487
488
|
end
|
@@ -520,7 +521,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
520
521
|
end
|
521
522
|
end
|
522
523
|
|
523
|
-
context "using trigram" do
|
524
|
+
context "when using trigram" do
|
524
525
|
before do
|
525
526
|
ModelWithPgSearch.pg_search_scope :with_trigrams, against: %i[title content], using: :trigram
|
526
527
|
end
|
@@ -562,13 +563,13 @@ describe "an Active Record model which includes PgSearch" do
|
|
562
563
|
end
|
563
564
|
end
|
564
565
|
|
565
|
-
context "using tsearch" do
|
566
|
+
context "when using tsearch" do
|
566
567
|
before do
|
567
568
|
ModelWithPgSearch.pg_search_scope :search_title_with_prefixes,
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
569
|
+
against: :title,
|
570
|
+
using: {
|
571
|
+
tsearch: { prefix: true }
|
572
|
+
}
|
572
573
|
end
|
573
574
|
|
574
575
|
context "with prefix: true" do
|
@@ -594,10 +595,10 @@ describe "an Active Record model which includes PgSearch" do
|
|
594
595
|
context "with the english dictionary" do
|
595
596
|
before do
|
596
597
|
ModelWithPgSearch.pg_search_scope :search_content_with_english,
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
598
|
+
against: :content,
|
599
|
+
using: {
|
600
|
+
tsearch: { dictionary: :english }
|
601
|
+
}
|
601
602
|
end
|
602
603
|
|
603
604
|
it "returns rows that match the query when stemmed by the english dictionary" do
|
@@ -620,7 +621,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
620
621
|
context "with highlight turned on" do
|
621
622
|
before do
|
622
623
|
ModelWithPgSearch.pg_search_scope :search_content,
|
623
|
-
|
624
|
+
against: :content
|
624
625
|
end
|
625
626
|
|
626
627
|
it "adds a #pg_search_highlight method to each returned model record" do
|
@@ -641,19 +642,19 @@ describe "an Active Record model which includes PgSearch" do
|
|
641
642
|
ModelWithPgSearch.create! content: "#{'text ' * 2}Let #{'text ' * 2}Let #{'text ' * 2}"
|
642
643
|
|
643
644
|
ModelWithPgSearch.pg_search_scope :search_content,
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
645
|
+
against: :content,
|
646
|
+
using: {
|
647
|
+
tsearch: {
|
648
|
+
highlight: {
|
649
|
+
StartSel: '<mark class="highlight">',
|
650
|
+
StopSel: '</mark>',
|
651
|
+
FragmentDelimiter: '<delim class="my_delim">',
|
652
|
+
MaxFragments: 2,
|
653
|
+
MaxWords: 2,
|
654
|
+
MinWords: 1
|
655
|
+
}
|
656
|
+
}
|
657
|
+
}
|
657
658
|
end
|
658
659
|
|
659
660
|
it "applies the options to the excerpts" do
|
@@ -682,10 +683,10 @@ describe "an Active Record model which includes PgSearch" do
|
|
682
683
|
context "with a normalization specified" do
|
683
684
|
before do
|
684
685
|
ModelWithPgSearch.pg_search_scope :search_content_with_normalization,
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
686
|
+
against: :content,
|
687
|
+
using: {
|
688
|
+
tsearch: { normalization: 2 }
|
689
|
+
}
|
689
690
|
end
|
690
691
|
|
691
692
|
it "ranks the results for documents with less text higher" do
|
@@ -699,8 +700,8 @@ describe "an Active Record model which includes PgSearch" do
|
|
699
700
|
context "with no normalization" do
|
700
701
|
before do
|
701
702
|
ModelWithPgSearch.pg_search_scope :search_content_without_normalization,
|
702
|
-
|
703
|
-
|
703
|
+
against: :content,
|
704
|
+
using: :tsearch
|
704
705
|
end
|
705
706
|
|
706
707
|
it "ranks the results equally" do
|
@@ -712,10 +713,10 @@ describe "an Active Record model which includes PgSearch" do
|
|
712
713
|
end
|
713
714
|
end
|
714
715
|
|
715
|
-
context "against columns ranked with arrays" do
|
716
|
+
context "when against columns ranked with arrays" do
|
716
717
|
before do
|
717
718
|
ModelWithPgSearch.pg_search_scope :search_weighted_by_array_of_arrays,
|
718
|
-
|
719
|
+
against: [[:content, 'B'], [:title, 'A']]
|
719
720
|
end
|
720
721
|
|
721
722
|
it "returns results sorted by weighted rank" do
|
@@ -728,10 +729,10 @@ describe "an Active Record model which includes PgSearch" do
|
|
728
729
|
end
|
729
730
|
end
|
730
731
|
|
731
|
-
context "against columns ranked with a hash" do
|
732
|
+
context "when against columns ranked with a hash" do
|
732
733
|
before do
|
733
734
|
ModelWithPgSearch.pg_search_scope :search_weighted_by_hash,
|
734
|
-
|
735
|
+
against: { content: 'B', title: 'A' }
|
735
736
|
end
|
736
737
|
|
737
738
|
it "returns results sorted by weighted rank" do
|
@@ -744,10 +745,10 @@ describe "an Active Record model which includes PgSearch" do
|
|
744
745
|
end
|
745
746
|
end
|
746
747
|
|
747
|
-
context "against columns of which only some are ranked" do
|
748
|
+
context "when against columns of which only some are ranked" do
|
748
749
|
before do
|
749
750
|
ModelWithPgSearch.pg_search_scope :search_weighted,
|
750
|
-
|
751
|
+
against: [:content, [:title, 'A']]
|
751
752
|
end
|
752
753
|
|
753
754
|
it "returns results sorted by weighted rank using an implied low rank for unranked columns" do
|
@@ -760,16 +761,16 @@ describe "an Active Record model which includes PgSearch" do
|
|
760
761
|
end
|
761
762
|
end
|
762
763
|
|
763
|
-
context "searching any_word option" do
|
764
|
+
context "when searching any_word option" do
|
764
765
|
before do
|
765
766
|
ModelWithPgSearch.pg_search_scope :search_title_with_any_word,
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
767
|
+
against: :title,
|
768
|
+
using: {
|
769
|
+
tsearch: { any_word: true }
|
770
|
+
}
|
770
771
|
|
771
772
|
ModelWithPgSearch.pg_search_scope :search_title_with_all_words,
|
772
|
-
|
773
|
+
against: :title
|
773
774
|
end
|
774
775
|
|
775
776
|
it "returns all results containing any word in their title" do
|
@@ -788,10 +789,10 @@ describe "an Active Record model which includes PgSearch" do
|
|
788
789
|
context "with :negation" do
|
789
790
|
before do
|
790
791
|
ModelWithPgSearch.pg_search_scope :search_with_negation,
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
792
|
+
against: :title,
|
793
|
+
using: {
|
794
|
+
tsearch: { negation: true }
|
795
|
+
}
|
795
796
|
end
|
796
797
|
|
797
798
|
it "doesn't return results that contain terms prepended with '!'" do
|
@@ -815,10 +816,10 @@ describe "an Active Record model which includes PgSearch" do
|
|
815
816
|
context "without :negation" do
|
816
817
|
before do
|
817
818
|
ModelWithPgSearch.pg_search_scope :search_without_negation,
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
819
|
+
against: :title,
|
820
|
+
using: {
|
821
|
+
tsearch: {}
|
822
|
+
}
|
822
823
|
end
|
823
824
|
|
824
825
|
it "return results that contain terms prepended with '!'" do
|
@@ -838,11 +839,11 @@ describe "an Active Record model which includes PgSearch" do
|
|
838
839
|
end
|
839
840
|
end
|
840
841
|
|
841
|
-
context "using dmetaphone" do
|
842
|
+
context "when using dmetaphone" do
|
842
843
|
before do
|
843
844
|
ModelWithPgSearch.pg_search_scope :with_dmetaphones,
|
844
|
-
|
845
|
-
|
845
|
+
against: %i[title content],
|
846
|
+
using: :dmetaphone
|
846
847
|
end
|
847
848
|
|
848
849
|
it "returns rows where one searchable column and the query share enough dmetaphones" do
|
@@ -877,38 +878,38 @@ describe "an Active Record model which includes PgSearch" do
|
|
877
878
|
end
|
878
879
|
end
|
879
880
|
|
880
|
-
context "using multiple features" do
|
881
|
+
context "when using multiple features" do
|
881
882
|
before do
|
882
883
|
ModelWithPgSearch.pg_search_scope :with_tsearch,
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
884
|
+
against: :title,
|
885
|
+
using: [
|
886
|
+
[:tsearch, { dictionary: 'english' }]
|
887
|
+
]
|
887
888
|
|
888
889
|
ModelWithPgSearch.pg_search_scope :with_trigram,
|
889
|
-
|
890
|
-
|
890
|
+
against: :title,
|
891
|
+
using: :trigram
|
891
892
|
|
892
893
|
ModelWithPgSearch.pg_search_scope :with_trigram_and_ignoring_accents,
|
893
|
-
|
894
|
-
|
895
|
-
|
894
|
+
against: :title,
|
895
|
+
ignoring: :accents,
|
896
|
+
using: :trigram
|
896
897
|
|
897
898
|
ModelWithPgSearch.pg_search_scope :with_tsearch_and_trigram,
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
899
|
+
against: :title,
|
900
|
+
using: [
|
901
|
+
[:tsearch, { dictionary: 'english' }],
|
902
|
+
:trigram
|
903
|
+
]
|
903
904
|
|
904
905
|
ModelWithPgSearch.pg_search_scope :complex_search,
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
906
|
+
against: %i[content title],
|
907
|
+
ignoring: :accents,
|
908
|
+
using: {
|
909
|
+
tsearch: { dictionary: 'english' },
|
910
|
+
dmetaphone: {},
|
911
|
+
trigram: {}
|
912
|
+
}
|
912
913
|
end
|
913
914
|
|
914
915
|
it "returns rows that match using any of the features" do
|
@@ -950,33 +951,40 @@ describe "an Active Record model which includes PgSearch" do
|
|
950
951
|
end
|
951
952
|
|
952
953
|
context "with feature-specific configuration" do
|
953
|
-
|
954
|
-
|
955
|
-
@trigram_config = trigram_config = { foo: 'bar' }
|
954
|
+
let(:tsearch_config) { { dictionary: 'english' } }
|
955
|
+
let(:trigram_config) { { foo: 'bar' } }
|
956
956
|
|
957
|
+
before do
|
957
958
|
ModelWithPgSearch.pg_search_scope :with_tsearch_and_trigram_using_hash,
|
958
|
-
|
959
|
-
|
960
|
-
tsearch: tsearch_config,
|
961
|
-
trigram: trigram_config
|
962
|
-
}
|
959
|
+
against: :title,
|
960
|
+
using: { tsearch: tsearch_config, trigram: trigram_config }
|
963
961
|
end
|
964
962
|
|
965
|
-
it "
|
966
|
-
|
963
|
+
it "passes the custom configuration down to the specified feature" do
|
964
|
+
tsearch_feature = instance_double(
|
965
|
+
"PgSearch::Features::TSearch",
|
966
|
+
conditions: Arel::Nodes::Grouping.new(Arel.sql("1 = 1")),
|
967
|
+
rank: Arel::Nodes::Grouping.new(Arel.sql("1.0"))
|
968
|
+
)
|
969
|
+
|
970
|
+
trigram_feature = instance_double(
|
971
|
+
"PgSearch::Features::Trigram",
|
967
972
|
conditions: Arel::Nodes::Grouping.new(Arel.sql("1 = 1")),
|
968
973
|
rank: Arel::Nodes::Grouping.new(Arel.sql("1.0"))
|
969
974
|
)
|
970
975
|
|
971
|
-
|
972
|
-
|
976
|
+
allow(PgSearch::Features::TSearch).to receive(:new).with(anything, tsearch_config, anything, anything, anything).and_return(tsearch_feature)
|
977
|
+
allow(PgSearch::Features::Trigram).to receive(:new).with(anything, trigram_config, anything, anything, anything).and_return(trigram_feature)
|
973
978
|
|
974
979
|
ModelWithPgSearch.with_tsearch_and_trigram_using_hash("foo")
|
980
|
+
|
981
|
+
expect(PgSearch::Features::TSearch).to have_received(:new).with(anything, tsearch_config, anything, anything, anything).at_least(:once)
|
982
|
+
expect(PgSearch::Features::Trigram).to have_received(:new).with(anything, trigram_config, anything, anything, anything).at_least(:once)
|
975
983
|
end
|
976
984
|
end
|
977
985
|
end
|
978
986
|
|
979
|
-
context "using a tsvector column and an association" do
|
987
|
+
context "when using a tsvector column and an association" do
|
980
988
|
with_model :Comment do
|
981
989
|
table do |t|
|
982
990
|
t.integer :post_id
|
@@ -995,7 +1003,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
995
1003
|
end
|
996
1004
|
|
997
1005
|
model do
|
998
|
-
include PgSearch
|
1006
|
+
include PgSearch::Model
|
999
1007
|
has_many :comments
|
1000
1008
|
end
|
1001
1009
|
end
|
@@ -1004,7 +1012,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
1004
1012
|
let!(:unexpected) { Post.create!(content: 'longcat is looooooooong') }
|
1005
1013
|
|
1006
1014
|
before do
|
1007
|
-
ActiveRecord::Base.connection.execute
|
1015
|
+
ActiveRecord::Base.connection.execute <<~SQL.squish
|
1008
1016
|
UPDATE #{Post.quoted_table_name}
|
1009
1017
|
SET content_tsvector = to_tsvector('english'::regconfig, #{Post.quoted_table_name}."content")
|
1010
1018
|
SQL
|
@@ -1013,41 +1021,41 @@ describe "an Active Record model which includes PgSearch" do
|
|
1013
1021
|
unexpected.comments.create(body: 'commentwo')
|
1014
1022
|
|
1015
1023
|
Post.pg_search_scope :search_by_content_with_tsvector,
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1024
|
+
associated_against: { comments: [:body] },
|
1025
|
+
using: {
|
1026
|
+
tsearch: {
|
1027
|
+
tsvector_column: 'content_tsvector',
|
1028
|
+
dictionary: 'english'
|
1029
|
+
}
|
1030
|
+
}
|
1023
1031
|
end
|
1024
1032
|
|
1025
|
-
it "
|
1033
|
+
it "finds by the tsvector column" do
|
1026
1034
|
expect(Post.search_by_content_with_tsvector("phooey").map(&:id)).to eq([expected.id])
|
1027
1035
|
end
|
1028
1036
|
|
1029
|
-
it "
|
1037
|
+
it "finds by the associated record" do
|
1030
1038
|
expect(Post.search_by_content_with_tsvector("commentone").map(&:id)).to eq([expected.id])
|
1031
1039
|
end
|
1032
1040
|
|
1033
|
-
it '
|
1041
|
+
it 'finds by a combination of the two' do
|
1034
1042
|
expect(Post.search_by_content_with_tsvector("phooey commentone").map(&:id)).to eq([expected.id])
|
1035
1043
|
end
|
1036
1044
|
end
|
1037
1045
|
|
1038
|
-
context 'using multiple tsvector columns' do
|
1046
|
+
context 'when using multiple tsvector columns' do
|
1039
1047
|
with_model :ModelWithTsvector do
|
1040
1048
|
model do
|
1041
|
-
include PgSearch
|
1049
|
+
include PgSearch::Model
|
1042
1050
|
|
1043
1051
|
pg_search_scope :search_by_multiple_tsvector_columns,
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1052
|
+
against: ['content', 'message'],
|
1053
|
+
using: {
|
1054
|
+
tsearch: {
|
1055
|
+
tsvector_column: ['content_tsvector', 'message_tsvector'],
|
1056
|
+
dictionary: 'english'
|
1057
|
+
}
|
1058
|
+
}
|
1051
1059
|
end
|
1052
1060
|
end
|
1053
1061
|
|
@@ -1059,40 +1067,41 @@ describe "an Active Record model which includes PgSearch" do
|
|
1059
1067
|
end
|
1060
1068
|
end
|
1061
1069
|
|
1062
|
-
context "using a tsvector column with" do
|
1070
|
+
context "when using a tsvector column with" do
|
1063
1071
|
with_model :ModelWithTsvector do
|
1064
1072
|
table do |t|
|
1065
1073
|
t.text 'content'
|
1066
1074
|
t.tsvector 'content_tsvector'
|
1067
1075
|
end
|
1068
1076
|
|
1069
|
-
model { include PgSearch }
|
1077
|
+
model { include PgSearch::Model }
|
1070
1078
|
end
|
1071
1079
|
|
1072
1080
|
let!(:expected) { ModelWithTsvector.create!(content: 'tiling is grouty') }
|
1073
|
-
let!(:unexpected) { ModelWithTsvector.create!(content: 'longcat is looooooooong') }
|
1074
1081
|
|
1075
1082
|
before do
|
1076
|
-
|
1083
|
+
ModelWithTsvector.create!(content: 'longcat is looooooooong')
|
1084
|
+
|
1085
|
+
ActiveRecord::Base.connection.execute <<~SQL.squish
|
1077
1086
|
UPDATE #{ModelWithTsvector.quoted_table_name}
|
1078
1087
|
SET content_tsvector = to_tsvector('english'::regconfig, #{ModelWithTsvector.quoted_table_name}."content")
|
1079
1088
|
SQL
|
1080
1089
|
|
1081
1090
|
ModelWithTsvector.pg_search_scope :search_by_content_with_tsvector,
|
1082
|
-
|
1083
|
-
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1091
|
+
against: :content,
|
1092
|
+
using: {
|
1093
|
+
tsearch: {
|
1094
|
+
tsvector_column: 'content_tsvector',
|
1095
|
+
dictionary: 'english'
|
1096
|
+
}
|
1097
|
+
}
|
1089
1098
|
end
|
1090
1099
|
|
1091
|
-
it "
|
1100
|
+
it "does not use to_tsvector in the query" do
|
1092
1101
|
expect(ModelWithTsvector.search_by_content_with_tsvector("tiles").to_sql).not_to match(/to_tsvector/)
|
1093
1102
|
end
|
1094
1103
|
|
1095
|
-
it "
|
1104
|
+
it "finds the expected result" do
|
1096
1105
|
expect(ModelWithTsvector.search_by_content_with_tsvector("tiles").map(&:id)).to eq([expected.id])
|
1097
1106
|
end
|
1098
1107
|
|
@@ -1108,7 +1117,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
1108
1117
|
ModelWithTsvector.has_many :another_models
|
1109
1118
|
end
|
1110
1119
|
|
1111
|
-
it "
|
1120
|
+
it "refers to the tsvector column in the query unambiguously" do
|
1112
1121
|
expect {
|
1113
1122
|
ModelWithTsvector.joins(:another_models).search_by_content_with_tsvector("test").to_a
|
1114
1123
|
}.not_to raise_exception
|
@@ -1116,11 +1125,11 @@ describe "an Active Record model which includes PgSearch" do
|
|
1116
1125
|
end
|
1117
1126
|
end
|
1118
1127
|
|
1119
|
-
context "ignoring accents" do
|
1128
|
+
context "when ignoring accents" do
|
1120
1129
|
before do
|
1121
1130
|
ModelWithPgSearch.pg_search_scope :search_title_without_accents,
|
1122
|
-
|
1123
|
-
|
1131
|
+
against: :title,
|
1132
|
+
ignoring: :accents
|
1124
1133
|
end
|
1125
1134
|
|
1126
1135
|
it "returns rows that match the query but not its accents" do
|
@@ -1146,24 +1155,24 @@ describe "an Active Record model which includes PgSearch" do
|
|
1146
1155
|
context "when passed a :ranked_by expression" do
|
1147
1156
|
before do
|
1148
1157
|
ModelWithPgSearch.pg_search_scope :search_content_with_default_rank,
|
1149
|
-
|
1158
|
+
against: :content
|
1150
1159
|
|
1151
1160
|
ModelWithPgSearch.pg_search_scope :search_content_with_importance_as_rank,
|
1152
|
-
|
1153
|
-
|
1161
|
+
against: :content,
|
1162
|
+
ranked_by: "importance"
|
1154
1163
|
|
1155
1164
|
ModelWithPgSearch.pg_search_scope :search_content_with_importance_as_rank_multiplier,
|
1156
|
-
|
1157
|
-
|
1165
|
+
against: :content,
|
1166
|
+
ranked_by: ":tsearch * importance"
|
1158
1167
|
end
|
1159
1168
|
|
1160
|
-
it "
|
1169
|
+
it "returns records with a rank attribute equal to the :ranked_by expression" do
|
1161
1170
|
ModelWithPgSearch.create!(content: 'foo', importance: 10)
|
1162
1171
|
results = ModelWithPgSearch.search_content_with_importance_as_rank("foo").with_pg_search_rank
|
1163
1172
|
expect(results.first.pg_search_rank).to eq(10)
|
1164
1173
|
end
|
1165
1174
|
|
1166
|
-
it "
|
1175
|
+
it "substitutes :tsearch with the tsearch rank expression in the :ranked_by expression" do
|
1167
1176
|
ModelWithPgSearch.create!(content: 'foo', importance: 10)
|
1168
1177
|
|
1169
1178
|
tsearch_result =
|
@@ -1181,7 +1190,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
1181
1190
|
expect(multiplied_rank).to be_within(0.001).of(tsearch_rank * 10)
|
1182
1191
|
end
|
1183
1192
|
|
1184
|
-
it "
|
1193
|
+
it "returns results in descending order of the value of the rank expression" do
|
1185
1194
|
records = [
|
1186
1195
|
ModelWithPgSearch.create!(content: 'foo', importance: 1),
|
1187
1196
|
ModelWithPgSearch.create!(content: 'foo', importance: 3),
|
@@ -1195,10 +1204,11 @@ describe "an Active Record model which includes PgSearch" do
|
|
1195
1204
|
%w[tsearch trigram dmetaphone].each do |feature|
|
1196
1205
|
context "using the #{feature} ranking algorithm" do
|
1197
1206
|
let(:scope_name) { :"search_content_ranked_by_#{feature}" }
|
1207
|
+
|
1198
1208
|
before do
|
1199
1209
|
ModelWithPgSearch.pg_search_scope scope_name,
|
1200
|
-
|
1201
|
-
|
1210
|
+
against: :content,
|
1211
|
+
ranked_by: ":#{feature}"
|
1202
1212
|
|
1203
1213
|
ModelWithPgSearch.create!(content: 'foo')
|
1204
1214
|
end
|
@@ -1231,12 +1241,12 @@ describe "an Active Record model which includes PgSearch" do
|
|
1231
1241
|
end
|
1232
1242
|
end
|
1233
1243
|
|
1234
|
-
context "using the tsearch ranking algorithm" do
|
1244
|
+
context "when using the tsearch ranking algorithm" do
|
1235
1245
|
it "sorts results by the tsearch rank" do
|
1236
1246
|
ModelWithPgSearch.pg_search_scope :search_content_ranked_by_tsearch,
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1247
|
+
using: :tsearch,
|
1248
|
+
against: :content,
|
1249
|
+
ranked_by: ":tsearch"
|
1240
1250
|
|
1241
1251
|
once = ModelWithPgSearch.create!(content: 'foo bar')
|
1242
1252
|
twice = ModelWithPgSearch.create!(content: 'foo foo')
|
@@ -1246,12 +1256,12 @@ describe "an Active Record model which includes PgSearch" do
|
|
1246
1256
|
end
|
1247
1257
|
end
|
1248
1258
|
|
1249
|
-
context "using the trigram ranking algorithm" do
|
1259
|
+
context "when using the trigram ranking algorithm" do
|
1250
1260
|
it "sorts results by the trigram rank" do
|
1251
1261
|
ModelWithPgSearch.pg_search_scope :search_content_ranked_by_trigram,
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1262
|
+
using: :trigram,
|
1263
|
+
against: :content,
|
1264
|
+
ranked_by: ":trigram"
|
1255
1265
|
|
1256
1266
|
close = ModelWithPgSearch.create!(content: 'abcdef')
|
1257
1267
|
exact = ModelWithPgSearch.create!(content: 'abc')
|
@@ -1261,12 +1271,12 @@ describe "an Active Record model which includes PgSearch" do
|
|
1261
1271
|
end
|
1262
1272
|
end
|
1263
1273
|
|
1264
|
-
context "using the dmetaphone ranking algorithm" do
|
1274
|
+
context "when using the dmetaphone ranking algorithm" do
|
1265
1275
|
it "sorts results by the dmetaphone rank" do
|
1266
1276
|
ModelWithPgSearch.pg_search_scope :search_content_ranked_by_dmetaphone,
|
1267
|
-
|
1268
|
-
|
1269
|
-
|
1277
|
+
using: :dmetaphone,
|
1278
|
+
against: :content,
|
1279
|
+
ranked_by: ":dmetaphone"
|
1270
1280
|
|
1271
1281
|
once = ModelWithPgSearch.create!(content: 'Phoo Bar')
|
1272
1282
|
twice = ModelWithPgSearch.create!(content: 'Phoo Fu')
|
@@ -1280,12 +1290,12 @@ describe "an Active Record model which includes PgSearch" do
|
|
1280
1290
|
context "when there is a sort only feature" do
|
1281
1291
|
it "excludes that feature from the conditions, but uses it in the sorting" do
|
1282
1292
|
ModelWithPgSearch.pg_search_scope :search_content_ranked_by_dmetaphone,
|
1283
|
-
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1293
|
+
against: :content,
|
1294
|
+
using: {
|
1295
|
+
tsearch: { any_word: true, prefix: true },
|
1296
|
+
dmetaphone: { any_word: true, prefix: true, sort_only: true }
|
1297
|
+
},
|
1298
|
+
ranked_by: ":tsearch + (0.5 * :dmetaphone)"
|
1289
1299
|
|
1290
1300
|
exact = ModelWithPgSearch.create!(content: "ash hines")
|
1291
1301
|
one_exact_one_close = ModelWithPgSearch.create!(content: "ash heinz")
|
@@ -1298,3 +1308,4 @@ describe "an Active Record model which includes PgSearch" do
|
|
1298
1308
|
end
|
1299
1309
|
end
|
1300
1310
|
end
|
1311
|
+
# rubocop:enable RSpec/NestedGroups
|