pg_search 2.3.6 → 2.3.7
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/workflows/ci.yml +21 -16
- data/.standard.yml +6 -0
- data/CHANGELOG.md +11 -0
- data/Gemfile +19 -6
- data/LICENSE +1 -1
- data/README.md +49 -32
- data/Rakefile +4 -7
- data/lib/pg_search/configuration/column.rb +6 -4
- data/lib/pg_search/configuration/foreign_column.rb +1 -1
- data/lib/pg_search/configuration.rb +1 -1
- data/lib/pg_search/document.rb +8 -8
- data/lib/pg_search/features/dmetaphone.rb +1 -1
- data/lib/pg_search/features/trigram.rb +4 -4
- data/lib/pg_search/features/tsearch.rb +14 -13
- data/lib/pg_search/migration/dmetaphone_generator.rb +2 -2
- data/lib/pg_search/migration/generator.rb +5 -5
- data/lib/pg_search/migration/multisearch_generator.rb +2 -2
- data/lib/pg_search/model.rb +6 -6
- data/lib/pg_search/multisearch.rb +4 -2
- data/lib/pg_search/multisearchable.rb +7 -7
- data/lib/pg_search/normalizer.rb +5 -5
- data/lib/pg_search/scope_options.rb +26 -5
- data/lib/pg_search/tasks.rb +2 -2
- data/lib/pg_search/version.rb +1 -1
- data/lib/pg_search.rb +3 -3
- data/pg_search.gemspec +16 -31
- data/spec/.rubocop.yml +20 -7
- data/spec/integration/.rubocop.yml +2 -2
- data/spec/integration/associations_spec.rb +106 -106
- data/spec/integration/deprecation_spec.rb +7 -8
- data/spec/integration/pg_search_spec.rb +314 -298
- data/spec/integration/single_table_inheritance_spec.rb +5 -5
- data/spec/lib/pg_search/configuration/association_spec.rb +15 -15
- data/spec/lib/pg_search/configuration/column_spec.rb +13 -1
- data/spec/lib/pg_search/configuration/foreign_column_spec.rb +4 -4
- data/spec/lib/pg_search/features/dmetaphone_spec.rb +4 -4
- data/spec/lib/pg_search/features/trigram_spec.rb +29 -29
- data/spec/lib/pg_search/features/tsearch_spec.rb +57 -39
- data/spec/lib/pg_search/multisearch/rebuilder_spec.rb +17 -17
- data/spec/lib/pg_search/multisearch_spec.rb +6 -6
- data/spec/lib/pg_search/multisearchable_spec.rb +26 -26
- data/spec/lib/pg_search/normalizer_spec.rb +7 -7
- data/spec/lib/pg_search_spec.rb +18 -18
- data/spec/spec_helper.rb +7 -9
- data/spec/support/database.rb +6 -6
- metadata +10 -214
- data/.codeclimate.yml +0 -17
- data/.rubocop.yml +0 -137
- data/.travis.yml +0 -37
@@ -6,8 +6,8 @@ describe "a pg_search_scope on an STI subclass" do
|
|
6
6
|
context "with the standard type column" do
|
7
7
|
with_model :SuperclassModel do
|
8
8
|
table do |t|
|
9
|
-
t.text
|
10
|
-
t.string
|
9
|
+
t.text "content"
|
10
|
+
t.string "type"
|
11
11
|
end
|
12
12
|
|
13
13
|
model do
|
@@ -46,13 +46,13 @@ describe "a pg_search_scope on an STI subclass" do
|
|
46
46
|
context "with a custom type column" do
|
47
47
|
with_model :SuperclassModel do
|
48
48
|
table do |t|
|
49
|
-
t.text
|
50
|
-
t.string
|
49
|
+
t.text "content"
|
50
|
+
t.string "custom_type"
|
51
51
|
end
|
52
52
|
|
53
53
|
model do
|
54
54
|
include PgSearch::Model
|
55
|
-
self.inheritance_column =
|
55
|
+
self.inheritance_column = "custom_type"
|
56
56
|
pg_search_scope :search_content, against: :content
|
57
57
|
end
|
58
58
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
require "spec_helper"
|
4
4
|
|
5
|
-
#
|
5
|
+
# standard:disable RSpec/NestedGroups
|
6
6
|
describe PgSearch::Configuration::Association do
|
7
7
|
with_model :Avatar do
|
8
8
|
table do |t|
|
@@ -22,8 +22,8 @@ describe PgSearch::Configuration::Association do
|
|
22
22
|
has_one :avatar, class_name: "Avatar"
|
23
23
|
belongs_to :site
|
24
24
|
|
25
|
-
pg_search_scope :with_avatar, associated_against: {
|
26
|
-
pg_search_scope :with_site, associated_against: {
|
25
|
+
pg_search_scope :with_avatar, associated_against: {avatar: :url}
|
26
|
+
pg_search_scope :with_site, associated_against: {site: :title}
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
@@ -36,7 +36,7 @@ describe PgSearch::Configuration::Association do
|
|
36
36
|
include PgSearch::Model
|
37
37
|
has_many :users, class_name: "User"
|
38
38
|
|
39
|
-
pg_search_scope :with_users, associated_against: {
|
39
|
+
pg_search_scope :with_users, associated_against: {users: :name}
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
@@ -55,9 +55,9 @@ describe PgSearch::Configuration::Association do
|
|
55
55
|
LEFT OUTER JOIN
|
56
56
|
(SELECT model_id AS id,
|
57
57
|
#{column_select} AS #{association.columns.first.alias}
|
58
|
-
FROM
|
59
|
-
INNER JOIN
|
60
|
-
ON
|
58
|
+
FROM "#{User.table_name}"
|
59
|
+
INNER JOIN "#{association.table_name}"
|
60
|
+
ON "#{association.table_name}"."user_id" = "#{User.table_name}"."id") #{association.subselect_alias}
|
61
61
|
ON #{association.subselect_alias}.id = model_id
|
62
62
|
SQL
|
63
63
|
end
|
@@ -86,9 +86,9 @@ describe PgSearch::Configuration::Association do
|
|
86
86
|
LEFT OUTER JOIN
|
87
87
|
(SELECT model_id AS id,
|
88
88
|
#{column_select} AS #{association.columns.first.alias}
|
89
|
-
FROM
|
90
|
-
INNER JOIN
|
91
|
-
ON
|
89
|
+
FROM "#{User.table_name}"
|
90
|
+
INNER JOIN "#{association.table_name}"
|
91
|
+
ON "#{association.table_name}"."id" = "#{User.table_name}"."site_id") #{association.subselect_alias}
|
92
92
|
ON #{association.subselect_alias}.id = model_id
|
93
93
|
SQL
|
94
94
|
end
|
@@ -116,10 +116,10 @@ describe PgSearch::Configuration::Association do
|
|
116
116
|
<<~SQL.squish
|
117
117
|
LEFT OUTER JOIN
|
118
118
|
(SELECT model_id AS id,
|
119
|
-
string_agg(
|
120
|
-
FROM
|
121
|
-
INNER JOIN
|
122
|
-
ON
|
119
|
+
string_agg("#{association.table_name}"."name"::text, ' ') AS #{association.columns.first.alias}
|
120
|
+
FROM "#{Site.table_name}"
|
121
|
+
INNER JOIN "#{association.table_name}"
|
122
|
+
ON "#{association.table_name}"."site_id" = "#{Site.table_name}"."id"
|
123
123
|
GROUP BY model_id) #{association.subselect_alias}
|
124
124
|
ON #{association.subselect_alias}.id = model_id
|
125
125
|
SQL
|
@@ -139,4 +139,4 @@ describe PgSearch::Configuration::Association do
|
|
139
139
|
end
|
140
140
|
end
|
141
141
|
end
|
142
|
-
#
|
142
|
+
# standard:enable RSpec/NestedGroups
|
@@ -7,6 +7,7 @@ describe PgSearch::Configuration::Column do
|
|
7
7
|
with_model :Model do
|
8
8
|
table do |t|
|
9
9
|
t.string :name
|
10
|
+
t.json :object
|
10
11
|
end
|
11
12
|
end
|
12
13
|
|
@@ -14,18 +15,29 @@ describe PgSearch::Configuration::Column do
|
|
14
15
|
column = described_class.new("name", nil, Model)
|
15
16
|
expect(column.full_name).to eq(%(#{Model.quoted_table_name}."name"))
|
16
17
|
end
|
18
|
+
|
19
|
+
it "returns nested json attributes" do
|
20
|
+
column = described_class.new(Arel.sql("object->>'name'"), nil, Model)
|
21
|
+
expect(column.full_name).to eq(%(object->>'name'))
|
22
|
+
end
|
17
23
|
end
|
18
24
|
|
19
25
|
describe "#to_sql" do
|
20
26
|
with_model :Model do
|
21
27
|
table do |t|
|
22
28
|
t.string :name
|
29
|
+
t.json :object
|
23
30
|
end
|
24
31
|
end
|
25
32
|
|
26
33
|
it "returns an expression that casts the column to text and coalesces it with an empty string" do
|
27
34
|
column = described_class.new("name", nil, Model)
|
28
|
-
expect(column.to_sql).to eq(%{coalesce(#{Model.quoted_table_name}."name"::text, '')})
|
35
|
+
expect(column.to_sql).to eq(%{coalesce((#{Model.quoted_table_name}."name")::text, '')})
|
36
|
+
end
|
37
|
+
|
38
|
+
it "returns an expression that casts the nested json attribute to text and coalesces it with an empty string" do
|
39
|
+
column = described_class.new(Arel.sql("object->>'name'"), nil, Model)
|
40
|
+
expect(column.to_sql).to eq(%{coalesce((object->>'name')::text, '')})
|
29
41
|
end
|
30
42
|
end
|
31
43
|
end
|
@@ -18,16 +18,16 @@ describe PgSearch::Configuration::ForeignColumn do
|
|
18
18
|
|
19
19
|
model do
|
20
20
|
include PgSearch::Model
|
21
|
-
belongs_to :another_model, class_name:
|
21
|
+
belongs_to :another_model, class_name: "AssociatedModel"
|
22
22
|
|
23
|
-
pg_search_scope :with_another, associated_against: {
|
23
|
+
pg_search_scope :with_another, associated_against: {another_model: :title}
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
27
|
it "returns a consistent string" do
|
28
28
|
association = PgSearch::Configuration::Association.new(Model,
|
29
|
-
|
30
|
-
|
29
|
+
:another_model,
|
30
|
+
:title)
|
31
31
|
foreign_column = described_class.new("title", nil, Model, association)
|
32
32
|
|
33
33
|
column_alias = foreign_column.alias
|
@@ -18,12 +18,12 @@ describe PgSearch::Features::DMetaphone do
|
|
18
18
|
PgSearch::Configuration::Column.new(:content, nil, Model)
|
19
19
|
]
|
20
20
|
options = {}
|
21
|
-
config = instance_double(
|
21
|
+
config = instance_double(PgSearch::Configuration, :config, ignore: [])
|
22
22
|
normalizer = PgSearch::Normalizer.new(config)
|
23
23
|
|
24
24
|
feature = described_class.new(query, options, columns, Model, normalizer)
|
25
25
|
expect(feature.rank.to_sql).to eq(
|
26
|
-
%{(ts_rank((to_tsvector('simple', pg_search_dmetaphone(coalesce(#{Model.quoted_table_name}."name"::text, ''))) || to_tsvector('simple', pg_search_dmetaphone(coalesce(#{Model.quoted_table_name}."content"::text, '')))), (to_tsquery('simple', ''' ' || pg_search_dmetaphone('query') || ' ''')), 0))}
|
26
|
+
%{(ts_rank((to_tsvector('simple', pg_search_dmetaphone(coalesce((#{Model.quoted_table_name}."name")::text, ''))) || to_tsvector('simple', pg_search_dmetaphone(coalesce((#{Model.quoted_table_name}."content")::text, '')))), (to_tsquery('simple', ''' ' || pg_search_dmetaphone('query') || ' ''')), 0))}
|
27
27
|
)
|
28
28
|
end
|
29
29
|
end
|
@@ -43,12 +43,12 @@ describe PgSearch::Features::DMetaphone do
|
|
43
43
|
PgSearch::Configuration::Column.new(:content, nil, Model)
|
44
44
|
]
|
45
45
|
options = {}
|
46
|
-
config = instance_double(
|
46
|
+
config = instance_double(PgSearch::Configuration, :config, ignore: [])
|
47
47
|
normalizer = PgSearch::Normalizer.new(config)
|
48
48
|
|
49
49
|
feature = described_class.new(query, options, columns, Model, normalizer)
|
50
50
|
expect(feature.conditions.to_sql).to eq(
|
51
|
-
%{((to_tsvector('simple', pg_search_dmetaphone(coalesce(#{Model.quoted_table_name}."name"::text, ''))) || to_tsvector('simple', pg_search_dmetaphone(coalesce(#{Model.quoted_table_name}."content"::text, '')))) @@ (to_tsquery('simple', ''' ' || pg_search_dmetaphone('query') || ' ''')))}
|
51
|
+
%{((to_tsvector('simple', pg_search_dmetaphone(coalesce((#{Model.quoted_table_name}."name")::text, ''))) || to_tsvector('simple', pg_search_dmetaphone(coalesce((#{Model.quoted_table_name}."content")::text, '')))) @@ (to_tsquery('simple', ''' ' || pg_search_dmetaphone('query') || ' ''')))}
|
52
52
|
)
|
53
53
|
end
|
54
54
|
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "spec_helper"
|
4
|
+
require "ostruct"
|
5
5
|
|
6
|
-
#
|
6
|
+
# standard:disable RSpec/MultipleMemoizedHelpers, RSpec/NestedGroups
|
7
7
|
describe PgSearch::Features::Trigram do
|
8
8
|
subject(:feature) { described_class.new(query, options, columns, Model, normalizer) }
|
9
9
|
|
10
|
-
let(:query) {
|
10
|
+
let(:query) { "lolwut" }
|
11
11
|
let(:options) { {} }
|
12
12
|
let(:columns) {
|
13
13
|
[
|
@@ -16,13 +16,13 @@ describe PgSearch::Features::Trigram do
|
|
16
16
|
]
|
17
17
|
}
|
18
18
|
let(:normalizer) { PgSearch::Normalizer.new(config) }
|
19
|
-
let(:config) { OpenStruct.new(ignore: []) }
|
19
|
+
let(:config) { OpenStruct.new(ignore: []) }
|
20
20
|
|
21
21
|
let(:coalesced_columns) do
|
22
22
|
<<~SQL.squish
|
23
|
-
coalesce(#{Model.quoted_table_name}."name"::text, '')
|
23
|
+
coalesce((#{Model.quoted_table_name}."name")::text, '')
|
24
24
|
|| ' '
|
25
|
-
|| coalesce(#{Model.quoted_table_name}."content"::text, '')
|
25
|
+
|| coalesce((#{Model.quoted_table_name}."content")::text, '')
|
26
26
|
SQL
|
27
27
|
end
|
28
28
|
|
@@ -33,15 +33,15 @@ describe PgSearch::Features::Trigram do
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
-
describe
|
37
|
-
it
|
36
|
+
describe "conditions" do
|
37
|
+
it "escapes the search document and query" do
|
38
38
|
config.ignore = []
|
39
39
|
expect(feature.conditions.to_sql).to eq("('#{query}' % (#{coalesced_columns}))")
|
40
40
|
end
|
41
41
|
|
42
|
-
context
|
42
|
+
context "when searching by word_similarity" do
|
43
43
|
let(:options) do
|
44
|
-
{
|
44
|
+
{word_similarity: true}
|
45
45
|
end
|
46
46
|
|
47
47
|
it 'uses the "<%" operator when searching by word_similarity' do
|
@@ -50,17 +50,17 @@ describe PgSearch::Features::Trigram do
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
-
context
|
54
|
-
it
|
53
|
+
context "when ignoring accents" do
|
54
|
+
it "escapes the search document and query, but not the accent function" do
|
55
55
|
config.ignore = [:accents]
|
56
56
|
expect(feature.conditions.to_sql).to eq("(unaccent('#{query}') % (unaccent(#{coalesced_columns})))")
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
|
-
context
|
61
|
-
context
|
60
|
+
context "when a threshold is specified" do
|
61
|
+
context "when searching by similarity" do
|
62
62
|
let(:options) do
|
63
|
-
{
|
63
|
+
{threshold: 0.5}
|
64
64
|
end
|
65
65
|
|
66
66
|
it 'uses a minimum similarity expression instead of the "%" operator' do
|
@@ -70,9 +70,9 @@ describe PgSearch::Features::Trigram do
|
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
|
-
context
|
73
|
+
context "when searching by word_similarity" do
|
74
74
|
let(:options) do
|
75
|
-
{
|
75
|
+
{threshold: 0.5, word_similarity: true}
|
76
76
|
end
|
77
77
|
|
78
78
|
it 'uses a minimum similarity expression instead of the "<%" operator' do
|
@@ -83,30 +83,30 @@ describe PgSearch::Features::Trigram do
|
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
86
|
-
context
|
87
|
-
context
|
88
|
-
let(:options) { {
|
86
|
+
context "when only certain columns are selected" do
|
87
|
+
context "with one column" do
|
88
|
+
let(:options) { {only: :name} }
|
89
89
|
|
90
|
-
it
|
91
|
-
coalesced_column = "coalesce(#{Model.quoted_table_name}.\"name\"::text, '')"
|
90
|
+
it "only searches against the select column" do
|
91
|
+
coalesced_column = "coalesce((#{Model.quoted_table_name}.\"name\")::text, '')"
|
92
92
|
expect(feature.conditions.to_sql).to eq("('#{query}' % (#{coalesced_column}))")
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
96
|
-
context
|
97
|
-
let(:options) { {
|
96
|
+
context "with multiple columns" do
|
97
|
+
let(:options) { {only: %i[name content]} }
|
98
98
|
|
99
|
-
it
|
99
|
+
it "concatenates when multiples columns are selected" do
|
100
100
|
expect(feature.conditions.to_sql).to eq("('#{query}' % (#{coalesced_columns}))")
|
101
101
|
end
|
102
102
|
end
|
103
103
|
end
|
104
104
|
end
|
105
105
|
|
106
|
-
describe
|
107
|
-
it
|
106
|
+
describe "#rank" do
|
107
|
+
it "returns an expression using the similarity() function" do
|
108
108
|
expect(feature.rank.to_sql).to eq("(similarity('#{query}', (#{coalesced_columns})))")
|
109
109
|
end
|
110
110
|
end
|
111
111
|
end
|
112
|
-
#
|
112
|
+
# standard:enable RSpec/MultipleMemoizedHelpers, RSpec/NestedGroups
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "spec_helper"
|
4
|
-
require "active_support/
|
4
|
+
require "active_support/core_ext/kernel/reporting"
|
5
5
|
|
6
6
|
describe PgSearch::Features::TSearch do
|
7
7
|
describe "#rank" do
|
@@ -19,14 +19,32 @@ describe PgSearch::Features::TSearch do
|
|
19
19
|
PgSearch::Configuration::Column.new(:content, nil, Model)
|
20
20
|
]
|
21
21
|
options = {}
|
22
|
-
config = instance_double(
|
22
|
+
config = instance_double(PgSearch::Configuration, :config, ignore: [])
|
23
23
|
normalizer = PgSearch::Normalizer.new(config)
|
24
24
|
|
25
25
|
feature = described_class.new(query, options, columns, Model, normalizer)
|
26
26
|
expect(feature.rank.to_sql).to eq(
|
27
|
-
%{(ts_rank((to_tsvector('simple', coalesce(#{Model.quoted_table_name}."name"::text, '')) || to_tsvector('simple', coalesce(#{Model.quoted_table_name}."content"::text, ''))), (to_tsquery('simple', ''' ' || 'query' || ' ''')), 0))}
|
27
|
+
%{(ts_rank((to_tsvector('simple', coalesce((#{Model.quoted_table_name}."name")::text, '')) || to_tsvector('simple', coalesce((#{Model.quoted_table_name}."content")::text, ''))), (to_tsquery('simple', ''' ' || 'query' || ' ''')), 0))}
|
28
28
|
)
|
29
29
|
end
|
30
|
+
|
31
|
+
context "with a tsvector column and a custom normalization" do
|
32
|
+
it "works?" do
|
33
|
+
query = "query"
|
34
|
+
columns = [
|
35
|
+
PgSearch::Configuration::Column.new(:name, nil, Model),
|
36
|
+
PgSearch::Configuration::Column.new(:content, nil, Model)
|
37
|
+
]
|
38
|
+
options = {tsvector_column: :my_tsvector, normalization: 2}
|
39
|
+
config = instance_double(PgSearch::Configuration, :config, ignore: [])
|
40
|
+
normalizer = PgSearch::Normalizer.new(config)
|
41
|
+
|
42
|
+
feature = described_class.new(query, options, columns, Model, normalizer)
|
43
|
+
expect(feature.rank.to_sql).to eq(
|
44
|
+
%{(ts_rank((#{Model.quoted_table_name}."my_tsvector"), (to_tsquery('simple', ''' ' || 'query' || ' ''')), 2))}
|
45
|
+
)
|
46
|
+
end
|
47
|
+
end
|
30
48
|
end
|
31
49
|
|
32
50
|
describe "#conditions" do
|
@@ -44,12 +62,12 @@ describe PgSearch::Features::TSearch do
|
|
44
62
|
PgSearch::Configuration::Column.new(:content, nil, Model)
|
45
63
|
]
|
46
64
|
options = {}
|
47
|
-
config = instance_double(
|
65
|
+
config = instance_double(PgSearch::Configuration, :config, ignore: [])
|
48
66
|
normalizer = PgSearch::Normalizer.new(config)
|
49
67
|
|
50
68
|
feature = described_class.new(query, options, columns, Model, normalizer)
|
51
69
|
expect(feature.conditions.to_sql).to eq(
|
52
|
-
%{((to_tsvector('simple', coalesce(#{Model.quoted_table_name}."name"::text, '')) || to_tsvector('simple', coalesce(#{Model.quoted_table_name}."content"::text, ''))) @@ (to_tsquery('simple', ''' ' || 'query' || ' ''')))}
|
70
|
+
%{((to_tsvector('simple', coalesce((#{Model.quoted_table_name}."name")::text, '')) || to_tsvector('simple', coalesce((#{Model.quoted_table_name}."content")::text, ''))) @@ (to_tsquery('simple', ''' ' || 'query' || ' ''')))}
|
53
71
|
)
|
54
72
|
end
|
55
73
|
|
@@ -60,13 +78,13 @@ describe PgSearch::Features::TSearch do
|
|
60
78
|
PgSearch::Configuration::Column.new(:name, nil, Model),
|
61
79
|
PgSearch::Configuration::Column.new(:content, nil, Model)
|
62
80
|
]
|
63
|
-
options = {
|
64
|
-
config = instance_double(
|
81
|
+
options = {negation: true}
|
82
|
+
config = instance_double(PgSearch::Configuration, :config, ignore: [])
|
65
83
|
normalizer = PgSearch::Normalizer.new(config)
|
66
84
|
|
67
85
|
feature = described_class.new(query, options, columns, Model, normalizer)
|
68
86
|
expect(feature.conditions.to_sql).to eq(
|
69
|
-
%{((to_tsvector('simple', coalesce(#{Model.quoted_table_name}."name"::text, '')) || to_tsvector('simple', coalesce(#{Model.quoted_table_name}."content"::text, ''))) @@ (to_tsquery('simple', '!' || ''' ' || 'query' || ' ''')))}
|
87
|
+
%{((to_tsvector('simple', coalesce((#{Model.quoted_table_name}."name")::text, '')) || to_tsvector('simple', coalesce((#{Model.quoted_table_name}."content")::text, ''))) @@ (to_tsquery('simple', '!' || ''' ' || 'query' || ' ''')))}
|
70
88
|
)
|
71
89
|
end
|
72
90
|
end
|
@@ -78,49 +96,49 @@ describe PgSearch::Features::TSearch do
|
|
78
96
|
PgSearch::Configuration::Column.new(:name, nil, Model),
|
79
97
|
PgSearch::Configuration::Column.new(:content, nil, Model)
|
80
98
|
]
|
81
|
-
options = {
|
82
|
-
config = instance_double(
|
99
|
+
options = {negation: false}
|
100
|
+
config = instance_double(PgSearch::Configuration, :config, ignore: [])
|
83
101
|
normalizer = PgSearch::Normalizer.new(config)
|
84
102
|
|
85
103
|
feature = described_class.new(query, options, columns, Model, normalizer)
|
86
104
|
expect(feature.conditions.to_sql).to eq(
|
87
|
-
%{((to_tsvector('simple', coalesce(#{Model.quoted_table_name}."name"::text, '')) || to_tsvector('simple', coalesce(#{Model.quoted_table_name}."content"::text, ''))) @@ (to_tsquery('simple', ''' ' || '!query' || ' ''')))}
|
105
|
+
%{((to_tsvector('simple', coalesce((#{Model.quoted_table_name}."name")::text, '')) || to_tsvector('simple', coalesce((#{Model.quoted_table_name}."content")::text, ''))) @@ (to_tsquery('simple', ''' ' || '!query' || ' ''')))}
|
88
106
|
)
|
89
107
|
end
|
90
108
|
end
|
91
109
|
|
92
110
|
context "when options[:tsvector_column] is a string" do
|
93
|
-
it
|
111
|
+
it "uses the tsvector column" do
|
94
112
|
query = "query"
|
95
113
|
columns = [
|
96
114
|
PgSearch::Configuration::Column.new(:name, nil, Model),
|
97
115
|
PgSearch::Configuration::Column.new(:content, nil, Model)
|
98
116
|
]
|
99
|
-
options = {
|
100
|
-
config = instance_double(
|
117
|
+
options = {tsvector_column: "my_tsvector"}
|
118
|
+
config = instance_double(PgSearch::Configuration, :config, ignore: [])
|
101
119
|
normalizer = PgSearch::Normalizer.new(config)
|
102
120
|
|
103
121
|
feature = described_class.new(query, options, columns, Model, normalizer)
|
104
122
|
expect(feature.conditions.to_sql).to eq(
|
105
|
-
%{((#{Model.quoted_table_name}
|
123
|
+
%{((#{Model.quoted_table_name}."my_tsvector") @@ (to_tsquery('simple', ''' ' || 'query' || ' ''')))}
|
106
124
|
)
|
107
125
|
end
|
108
126
|
end
|
109
127
|
|
110
128
|
context "when options[:tsvector_column] is an array of strings" do
|
111
|
-
it
|
129
|
+
it "uses the tsvector column" do
|
112
130
|
query = "query"
|
113
131
|
columns = [
|
114
132
|
PgSearch::Configuration::Column.new(:name, nil, Model),
|
115
133
|
PgSearch::Configuration::Column.new(:content, nil, Model)
|
116
134
|
]
|
117
|
-
options = {
|
118
|
-
config = instance_double(
|
135
|
+
options = {tsvector_column: ["tsvector1", "tsvector2"]}
|
136
|
+
config = instance_double(PgSearch::Configuration, :config, ignore: [])
|
119
137
|
normalizer = PgSearch::Normalizer.new(config)
|
120
138
|
|
121
139
|
feature = described_class.new(query, options, columns, Model, normalizer)
|
122
140
|
expect(feature.conditions.to_sql).to eq(
|
123
|
-
%{((#{Model.quoted_table_name}
|
141
|
+
%{((#{Model.quoted_table_name}."tsvector1" || #{Model.quoted_table_name}."tsvector2") @@ (to_tsquery('simple', ''' ' || 'query' || ' ''')))}
|
124
142
|
)
|
125
143
|
end
|
126
144
|
end
|
@@ -141,18 +159,18 @@ describe PgSearch::Features::TSearch do
|
|
141
159
|
]
|
142
160
|
options = {}
|
143
161
|
|
144
|
-
config = instance_double(
|
162
|
+
config = instance_double(PgSearch::Configuration, :config, ignore: [])
|
145
163
|
normalizer = PgSearch::Normalizer.new(config)
|
146
164
|
|
147
165
|
feature = described_class.new(query, options, columns, Model, normalizer)
|
148
166
|
expect(feature.highlight.to_sql).to eq(
|
149
|
-
"(ts_headline('simple', (coalesce(#{Model.quoted_table_name}.\"name\"::text, '')), (to_tsquery('simple', ''' ' || 'query' || ' ''')), ''))"
|
167
|
+
"(ts_headline('simple', (coalesce((#{Model.quoted_table_name}.\"name\")::text, '')), (to_tsquery('simple', ''' ' || 'query' || ' ''')), ''))"
|
150
168
|
)
|
151
169
|
end
|
152
170
|
|
153
171
|
context "when options[:dictionary] is passed" do
|
154
|
-
#
|
155
|
-
it
|
172
|
+
# standard:disable RSpec/ExampleLength
|
173
|
+
it "uses the provided dictionary" do
|
156
174
|
query = "query"
|
157
175
|
columns = [
|
158
176
|
PgSearch::Configuration::Column.new(:name, nil, Model),
|
@@ -166,20 +184,20 @@ describe PgSearch::Features::TSearch do
|
|
166
184
|
}
|
167
185
|
}
|
168
186
|
|
169
|
-
config = instance_double(
|
187
|
+
config = instance_double(PgSearch::Configuration, :config, ignore: [])
|
170
188
|
normalizer = PgSearch::Normalizer.new(config)
|
171
189
|
|
172
190
|
feature = described_class.new(query, options, columns, Model, normalizer)
|
173
191
|
|
174
|
-
expected_sql = %{(ts_headline('spanish', (coalesce(#{Model.quoted_table_name}."name"::text, '') || ' ' || coalesce(#{Model.quoted_table_name}."content"::text, '')), (to_tsquery('spanish', ''' ' || 'query' || ' ''')), 'StartSel = "<b>", StopSel = "</b>"'))}
|
192
|
+
expected_sql = %{(ts_headline('spanish', (coalesce((#{Model.quoted_table_name}."name")::text, '') || ' ' || coalesce((#{Model.quoted_table_name}."content")::text, '')), (to_tsquery('spanish', ''' ' || 'query' || ' ''')), 'StartSel = "<b>", StopSel = "</b>"'))}
|
175
193
|
|
176
194
|
expect(feature.highlight.to_sql).to eq(expected_sql)
|
177
195
|
end
|
178
|
-
#
|
196
|
+
# standard:enable RSpec/ExampleLength
|
179
197
|
end
|
180
198
|
|
181
199
|
context "when options[:highlight] has options set" do
|
182
|
-
#
|
200
|
+
# standard:disable RSpec/ExampleLength
|
183
201
|
it "passes the options to ts_headline" do
|
184
202
|
query = "query"
|
185
203
|
columns = [
|
@@ -188,28 +206,28 @@ describe PgSearch::Features::TSearch do
|
|
188
206
|
options = {
|
189
207
|
highlight: {
|
190
208
|
StartSel: '<start class="search">',
|
191
|
-
StopSel:
|
209
|
+
StopSel: "<stop>",
|
192
210
|
MaxWords: 123,
|
193
211
|
MinWords: 456,
|
194
212
|
ShortWord: 4,
|
195
213
|
HighlightAll: true,
|
196
214
|
MaxFragments: 3,
|
197
|
-
FragmentDelimiter:
|
215
|
+
FragmentDelimiter: "…"
|
198
216
|
}
|
199
217
|
}
|
200
218
|
|
201
|
-
config = instance_double(
|
219
|
+
config = instance_double(PgSearch::Configuration, :config, ignore: [])
|
202
220
|
normalizer = PgSearch::Normalizer.new(config)
|
203
221
|
|
204
222
|
feature = described_class.new(query, options, columns, Model, normalizer)
|
205
223
|
|
206
|
-
expected_sql = %{(ts_headline('simple', (coalesce(#{Model.quoted_table_name}."name"::text, '')), (to_tsquery('simple', ''' ' || 'query' || ' ''')), 'StartSel = "<start class=""search"">", StopSel = "<stop>", MaxFragments = 3, MaxWords = 123, MinWords = 456, ShortWord = 4, FragmentDelimiter = "…", HighlightAll = TRUE'))}
|
224
|
+
expected_sql = %{(ts_headline('simple', (coalesce((#{Model.quoted_table_name}."name")::text, '')), (to_tsquery('simple', ''' ' || 'query' || ' ''')), 'StartSel = "<start class=""search"">", StopSel = "<stop>", MaxFragments = 3, MaxWords = 123, MinWords = 456, ShortWord = 4, FragmentDelimiter = "…", HighlightAll = TRUE'))}
|
207
225
|
|
208
226
|
expect(feature.highlight.to_sql).to eq(expected_sql)
|
209
227
|
end
|
210
|
-
#
|
228
|
+
# standard:enable RSpec/ExampleLength
|
211
229
|
|
212
|
-
#
|
230
|
+
# standard:disable RSpec/ExampleLength
|
213
231
|
it "passes deprecated options to ts_headline" do
|
214
232
|
query = "query"
|
215
233
|
columns = [
|
@@ -218,27 +236,27 @@ describe PgSearch::Features::TSearch do
|
|
218
236
|
options = {
|
219
237
|
highlight: {
|
220
238
|
start_sel: '<start class="search">',
|
221
|
-
stop_sel:
|
239
|
+
stop_sel: "<stop>",
|
222
240
|
max_words: 123,
|
223
241
|
min_words: 456,
|
224
242
|
short_word: 4,
|
225
243
|
highlight_all: false,
|
226
244
|
max_fragments: 3,
|
227
|
-
fragment_delimiter:
|
245
|
+
fragment_delimiter: "…"
|
228
246
|
}
|
229
247
|
}
|
230
248
|
|
231
|
-
config = instance_double(
|
249
|
+
config = instance_double(PgSearch::Configuration, :config, ignore: [])
|
232
250
|
normalizer = PgSearch::Normalizer.new(config)
|
233
251
|
|
234
252
|
feature = described_class.new(query, options, columns, Model, normalizer)
|
235
253
|
|
236
|
-
highlight_sql =
|
237
|
-
expected_sql = %{(ts_headline('simple', (coalesce(#{Model.quoted_table_name}."name"::text, '')), (to_tsquery('simple', ''' ' || 'query' || ' ''')), 'StartSel = "<start class=""search"">", StopSel = "<stop>", MaxFragments = 3, MaxWords = 123, MinWords = 456, ShortWord = 4, FragmentDelimiter = "…", HighlightAll = FALSE'))}
|
254
|
+
highlight_sql = silence_warnings { feature.highlight.to_sql }
|
255
|
+
expected_sql = %{(ts_headline('simple', (coalesce((#{Model.quoted_table_name}."name")::text, '')), (to_tsquery('simple', ''' ' || 'query' || ' ''')), 'StartSel = "<start class=""search"">", StopSel = "<stop>", MaxFragments = 3, MaxWords = 123, MinWords = 456, ShortWord = 4, FragmentDelimiter = "…", HighlightAll = FALSE'))}
|
238
256
|
|
239
257
|
expect(highlight_sql).to eq(expected_sql)
|
240
258
|
end
|
241
|
-
#
|
259
|
+
# standard:enable RSpec/ExampleLength
|
242
260
|
end
|
243
261
|
end
|
244
262
|
end
|