pg_search 2.3.2 → 2.3.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +11 -0
- data/.rubocop.yml +86 -4
- data/.travis.yml +4 -12
- data/CHANGELOG.md +25 -20
- data/LICENSE +1 -1
- data/README.md +5 -5
- data/lib/pg_search.rb +4 -4
- data/lib/pg_search/document.rb +1 -1
- data/lib/pg_search/features/dmetaphone.rb +4 -6
- 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 +2 -0
- data/lib/pg_search/multisearch.rb +10 -1
- data/lib/pg_search/multisearch/rebuilder.rb +2 -2
- data/lib/pg_search/scope_options.rb +2 -2
- data/lib/pg_search/tasks.rb +1 -1
- data/lib/pg_search/version.rb +1 -1
- data/pg_search.gemspec +8 -3
- data/spec/integration/.rubocop.yml +11 -0
- data/spec/integration/associations_spec.rb +17 -56
- data/spec/integration/deprecation_spec.rb +1 -1
- data/spec/integration/pg_search_spec.rb +62 -51
- data/spec/lib/pg_search/configuration/association_spec.rb +8 -6
- data/spec/lib/pg_search/features/dmetaphone_spec.rb +2 -2
- data/spec/lib/pg_search/features/trigram_spec.rb +15 -11
- data/spec/lib/pg_search/features/tsearch_spec.rb +16 -10
- data/spec/lib/pg_search/multisearch/rebuilder_spec.rb +89 -55
- data/spec/lib/pg_search/multisearch_spec.rb +47 -28
- data/spec/lib/pg_search/multisearchable_spec.rb +148 -94
- data/spec/lib/pg_search/normalizer_spec.rb +12 -10
- data/spec/lib/pg_search_spec.rb +57 -41
- data/spec/spec_helper.rb +10 -4
- data/spec/support/database.rb +1 -1
- metadata +81 -8
@@ -1,5 +1,5 @@
|
|
1
1
|
class CreatePgSearchDocuments < ActiveRecord::Migration<%= migration_version %>
|
2
|
-
def
|
2
|
+
def up
|
3
3
|
say_with_time("Creating table for pg_search multisearch") do
|
4
4
|
create_table :pg_search_documents do |t|
|
5
5
|
t.text :content
|
@@ -9,7 +9,7 @@ class CreatePgSearchDocuments < ActiveRecord::Migration<%= migration_version %>
|
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
12
|
+
def down
|
13
13
|
say_with_time("Dropping table for pg_search multisearch") do
|
14
14
|
drop_table :pg_search_documents
|
15
15
|
end
|
data/lib/pg_search/model.rb
CHANGED
@@ -21,11 +21,13 @@ module PgSearch
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
+
# rubocop:disable ThreadSafety/ClassAndModuleAttributes
|
24
25
|
def multisearchable(options = {})
|
25
26
|
include PgSearch::Multisearchable
|
26
27
|
class_attribute :pg_search_multisearchable_options
|
27
28
|
self.pg_search_multisearchable_options = options
|
28
29
|
end
|
30
|
+
# rubocop:enable ThreadSafety/ClassAndModuleAttributes
|
29
31
|
end
|
30
32
|
|
31
33
|
def method_missing(symbol, *args)
|
@@ -5,7 +5,15 @@ require "pg_search/multisearch/rebuilder"
|
|
5
5
|
module PgSearch
|
6
6
|
module Multisearch
|
7
7
|
class << self
|
8
|
-
def rebuild(model,
|
8
|
+
def rebuild(model, deprecated_clean_up = nil, clean_up: true)
|
9
|
+
unless deprecated_clean_up.nil?
|
10
|
+
ActiveSupport::Deprecation.warn(
|
11
|
+
"pg_search 3.0 will no longer accept a boolean second argument to PgSearchMultisearch.rebuild, " \
|
12
|
+
"use keyword argument `clean_up:` instead."
|
13
|
+
)
|
14
|
+
clean_up = deprecated_clean_up
|
15
|
+
end
|
16
|
+
|
9
17
|
model.transaction do
|
10
18
|
PgSearch::Document.where(searchable_type: model.base_class.name).delete_all if clean_up
|
11
19
|
Rebuilder.new(model).rebuild
|
@@ -15,6 +23,7 @@ module PgSearch
|
|
15
23
|
|
16
24
|
class ModelNotMultisearchable < StandardError
|
17
25
|
def initialize(model_class)
|
26
|
+
super
|
18
27
|
@model_class = model_class
|
19
28
|
end
|
20
29
|
|
@@ -30,7 +30,7 @@ module PgSearch
|
|
30
30
|
|
31
31
|
def dynamic?
|
32
32
|
column_names = model.columns.map(&:name)
|
33
|
-
columns.any? { |column|
|
33
|
+
columns.any? { |column| column_names.exclude?(column.to_s) }
|
34
34
|
end
|
35
35
|
|
36
36
|
def additional_attributes?
|
@@ -46,7 +46,7 @@ module PgSearch
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def rebuild_sql_template
|
49
|
-
|
49
|
+
<<~SQL.squish
|
50
50
|
INSERT INTO :documents_table (searchable_type, searchable_id, content, created_at, updated_at)
|
51
51
|
SELECT :base_model_name AS searchable_type,
|
52
52
|
:model_table.#{primary_key} AS searchable_id,
|
@@ -14,7 +14,7 @@ module PgSearch
|
|
14
14
|
|
15
15
|
def apply(scope)
|
16
16
|
scope = include_table_aliasing_for_rank(scope)
|
17
|
-
rank_table_alias = scope.pg_search_rank_table_alias(:
|
17
|
+
rank_table_alias = scope.pg_search_rank_table_alias(include_counter: true)
|
18
18
|
|
19
19
|
scope
|
20
20
|
.joins(rank_join(rank_table_alias))
|
@@ -58,7 +58,7 @@ module PgSearch
|
|
58
58
|
end
|
59
59
|
|
60
60
|
module PgSearchRankTableAliasing
|
61
|
-
def pg_search_rank_table_alias(include_counter
|
61
|
+
def pg_search_rank_table_alias(include_counter: false)
|
62
62
|
components = [arel_table.name]
|
63
63
|
if include_counter
|
64
64
|
count = increment_counter
|
data/lib/pg_search/tasks.rb
CHANGED
@@ -7,7 +7,7 @@ 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]
|
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
|
@@ -24,10 +24,15 @@ Gem::Specification.new do |s|
|
|
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
|
@@ -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|
|
@@ -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'
|
@@ -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'
|
@@ -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'
|
@@ -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'
|
@@ -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'
|
@@ -289,7 +290,7 @@ describe PgSearch do
|
|
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'
|
@@ -342,7 +343,7 @@ describe PgSearch do
|
|
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),
|
@@ -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
|
@@ -416,7 +417,7 @@ describe PgSearch do
|
|
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
|
@@ -461,48 +462,7 @@ describe PgSearch do
|
|
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::Model
|
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
|
@@ -23,7 +23,7 @@ describe "Including the deprecated PgSearch module" do
|
|
23
23
|
AnotherModel.include(PgSearch)
|
24
24
|
|
25
25
|
expect(ActiveSupport::Deprecation).to have_received(:warn).with(
|
26
|
-
|
26
|
+
<<~MESSAGE
|
27
27
|
Directly including `PgSearch` into an Active Record model is deprecated and will be removed in pg_search 3.0.
|
28
28
|
|
29
29
|
Please replace `include PgSearch` with `include PgSearch::Model`.
|
@@ -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|
|
@@ -64,7 +65,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
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 } }
|
@@ -87,7 +88,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
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 } }
|
@@ -110,7 +111,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
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 } }
|
@@ -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
|
@@ -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
|
|
@@ -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,7 +563,7 @@ 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
|
against: :title,
|
@@ -712,7 +713,7 @@ 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']]
|
@@ -728,7 +729,7 @@ 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' }
|
@@ -744,7 +745,7 @@ 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']]
|
@@ -760,7 +761,7 @@ 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
|
against: :title,
|
@@ -838,7 +839,7 @@ 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
|
against: %i[title content],
|
@@ -877,7 +878,7 @@ 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
|
against: :title,
|
@@ -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
|
against: :title,
|
959
|
-
using: {
|
960
|
-
tsearch: tsearch_config,
|
961
|
-
trigram: trigram_config
|
962
|
-
}
|
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",
|
967
966
|
conditions: Arel::Nodes::Grouping.new(Arel.sql("1 = 1")),
|
968
967
|
rank: Arel::Nodes::Grouping.new(Arel.sql("1.0"))
|
969
968
|
)
|
970
969
|
|
971
|
-
|
972
|
-
|
970
|
+
trigram_feature = instance_double(
|
971
|
+
"PgSearch::Features::Trigram",
|
972
|
+
conditions: Arel::Nodes::Grouping.new(Arel.sql("1 = 1")),
|
973
|
+
rank: Arel::Nodes::Grouping.new(Arel.sql("1.0"))
|
974
|
+
)
|
975
|
+
|
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
|
@@ -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
|
@@ -1022,20 +1030,20 @@ describe "an Active Record model which includes PgSearch" do
|
|
1022
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
1049
|
include PgSearch::Model
|
@@ -1059,7 +1067,7 @@ 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'
|
@@ -1070,10 +1078,11 @@ describe "an Active Record model which includes PgSearch" do
|
|
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
|
@@ -1088,11 +1097,11 @@ describe "an Active Record model which includes PgSearch" do
|
|
1088
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,7 +1125,7 @@ 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
1131
|
against: :title,
|
@@ -1157,13 +1166,13 @@ describe "an Active Record model which includes PgSearch" do
|
|
1157
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,6 +1204,7 @@ 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
1210
|
against: :content,
|
@@ -1231,7 +1241,7 @@ 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
1247
|
using: :tsearch,
|
@@ -1246,7 +1256,7 @@ 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
1262
|
using: :trigram,
|
@@ -1261,7 +1271,7 @@ 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
1277
|
using: :dmetaphone,
|
@@ -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
|