pg_search 2.3.2 → 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/.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
|