pg_search 2.2.0 → 2.3.4
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 +88 -7
- data/.travis.yml +11 -19
- data/CHANGELOG.md +40 -15
- data/Gemfile +1 -1
- data/LICENSE +1 -1
- data/README.md +46 -45
- data/lib/pg_search.rb +13 -56
- data/lib/pg_search/document.rb +2 -2
- 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 +57 -0
- data/lib/pg_search/multisearch.rb +10 -1
- data/lib/pg_search/multisearch/rebuilder.rb +7 -3
- data/lib/pg_search/scope_options.rb +2 -2
- data/lib/pg_search/tasks.rb +2 -1
- data/lib/pg_search/version.rb +1 -1
- data/pg_search.gemspec +9 -5
- data/spec/.rubocop.yml +2 -2
- data/spec/integration/.rubocop.yml +11 -0
- data/spec/integration/associations_spec.rb +27 -66
- data/spec/integration/deprecation_spec.rb +33 -0
- data/spec/integration/pagination_spec.rb +1 -1
- data/spec/integration/pg_search_spec.rb +70 -59
- 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 +1 -1
- 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 +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 +59 -46
- data/spec/spec_helper.rb +13 -4
- data/spec/support/database.rb +1 -1
- metadata +76 -13
@@ -11,7 +11,7 @@ describe "a pg_search_scope on an STI subclass" do
|
|
11
11
|
end
|
12
12
|
|
13
13
|
model do
|
14
|
-
include PgSearch
|
14
|
+
include PgSearch::Model
|
15
15
|
pg_search_scope :search_content, against: :content
|
16
16
|
end
|
17
17
|
end
|
@@ -51,7 +51,7 @@ describe "a pg_search_scope on an STI subclass" do
|
|
51
51
|
end
|
52
52
|
|
53
53
|
model do
|
54
|
-
include PgSearch
|
54
|
+
include PgSearch::Model
|
55
55
|
self.inheritance_column = 'custom_type'
|
56
56
|
pg_search_scope :search_content, against: :content
|
57
57
|
end
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "spec_helper"
|
4
4
|
|
5
|
+
# rubocop:disable RSpec/NestedGroups
|
5
6
|
describe PgSearch::Configuration::Association do
|
6
7
|
with_model :Avatar do
|
7
8
|
table do |t|
|
@@ -17,7 +18,7 @@ describe PgSearch::Configuration::Association do
|
|
17
18
|
end
|
18
19
|
|
19
20
|
model do
|
20
|
-
include PgSearch
|
21
|
+
include PgSearch::Model
|
21
22
|
has_one :avatar, class_name: "Avatar"
|
22
23
|
belongs_to :site
|
23
24
|
|
@@ -32,14 +33,14 @@ describe PgSearch::Configuration::Association do
|
|
32
33
|
end
|
33
34
|
|
34
35
|
model do
|
35
|
-
include PgSearch
|
36
|
+
include PgSearch::Model
|
36
37
|
has_many :users, class_name: "User"
|
37
38
|
|
38
39
|
pg_search_scope :with_users, associated_against: { users: :name }
|
39
40
|
end
|
40
41
|
end
|
41
42
|
|
42
|
-
context "has_one" do
|
43
|
+
context "with has_one" do
|
43
44
|
let(:association) { described_class.new(User, :avatar, :url) }
|
44
45
|
|
45
46
|
describe "#table_name" do
|
@@ -50,7 +51,7 @@ describe PgSearch::Configuration::Association do
|
|
50
51
|
|
51
52
|
describe "#join" do
|
52
53
|
let(:expected_sql) do
|
53
|
-
|
54
|
+
<<~SQL.squish
|
54
55
|
LEFT OUTER JOIN
|
55
56
|
(SELECT model_id AS id,
|
56
57
|
#{column_select} AS #{association.columns.first.alias}
|
@@ -70,7 +71,7 @@ describe PgSearch::Configuration::Association do
|
|
70
71
|
end
|
71
72
|
end
|
72
73
|
|
73
|
-
context "belongs_to" do
|
74
|
+
context "with belongs_to" do
|
74
75
|
let(:association) { described_class.new(User, :site, :title) }
|
75
76
|
|
76
77
|
describe "#table_name" do
|
@@ -81,7 +82,7 @@ describe PgSearch::Configuration::Association do
|
|
81
82
|
|
82
83
|
describe "#join" do
|
83
84
|
let(:expected_sql) do
|
84
|
-
|
85
|
+
<<~SQL.squish
|
85
86
|
LEFT OUTER JOIN
|
86
87
|
(SELECT model_id AS id,
|
87
88
|
#{column_select} AS #{association.columns.first.alias}
|
@@ -101,7 +102,7 @@ describe PgSearch::Configuration::Association do
|
|
101
102
|
end
|
102
103
|
end
|
103
104
|
|
104
|
-
context "has_many" do
|
105
|
+
context "with has_many" do
|
105
106
|
let(:association) { described_class.new(Site, :users, :name) }
|
106
107
|
|
107
108
|
describe "#table_name" do
|
@@ -112,7 +113,7 @@ describe PgSearch::Configuration::Association do
|
|
112
113
|
|
113
114
|
describe "#join" do
|
114
115
|
let(:expected_sql) do
|
115
|
-
|
116
|
+
<<~SQL.squish
|
116
117
|
LEFT OUTER JOIN
|
117
118
|
(SELECT model_id AS id,
|
118
119
|
string_agg(\"#{association.table_name}\".\"name\"::text, ' ') AS #{association.columns.first.alias}
|
@@ -138,3 +139,4 @@ describe PgSearch::Configuration::Association do
|
|
138
139
|
end
|
139
140
|
end
|
140
141
|
end
|
142
|
+
# rubocop:enable RSpec/NestedGroups
|
@@ -17,7 +17,7 @@ describe PgSearch::Configuration::ForeignColumn do
|
|
17
17
|
end
|
18
18
|
|
19
19
|
model do
|
20
|
-
include PgSearch
|
20
|
+
include PgSearch::Model
|
21
21
|
belongs_to :another_model, class_name: 'AssociatedModel'
|
22
22
|
|
23
23
|
pg_search_scope :with_another, associated_against: { another_model: :title }
|
@@ -18,7 +18,7 @@ describe PgSearch::Features::DMetaphone do
|
|
18
18
|
PgSearch::Configuration::Column.new(:content, nil, Model)
|
19
19
|
]
|
20
20
|
options = {}
|
21
|
-
config =
|
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)
|
@@ -43,7 +43,7 @@ describe PgSearch::Features::DMetaphone do
|
|
43
43
|
PgSearch::Configuration::Column.new(:content, nil, Model)
|
44
44
|
]
|
45
45
|
options = {}
|
46
|
-
config =
|
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)
|
@@ -3,8 +3,10 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
require 'ostruct'
|
5
5
|
|
6
|
+
# rubocop:disable RSpec/MultipleMemoizedHelpers, RSpec/NestedGroups
|
6
7
|
describe PgSearch::Features::Trigram do
|
7
8
|
subject(:feature) { described_class.new(query, options, columns, Model, normalizer) }
|
9
|
+
|
8
10
|
let(:query) { 'lolwut' }
|
9
11
|
let(:options) { {} }
|
10
12
|
let(:columns) {
|
@@ -17,8 +19,10 @@ describe PgSearch::Features::Trigram do
|
|
17
19
|
let(:config) { OpenStruct.new(ignore: []) }
|
18
20
|
|
19
21
|
let(:coalesced_columns) do
|
20
|
-
|
21
|
-
coalesce(#{Model.quoted_table_name}."name"::text, '')
|
22
|
+
<<~SQL.squish
|
23
|
+
coalesce(#{Model.quoted_table_name}."name"::text, '')
|
24
|
+
|| ' '
|
25
|
+
|| coalesce(#{Model.quoted_table_name}."content"::text, '')
|
22
26
|
SQL
|
23
27
|
end
|
24
28
|
|
@@ -35,7 +39,7 @@ describe PgSearch::Features::Trigram do
|
|
35
39
|
expect(feature.conditions.to_sql).to eq("('#{query}' % (#{coalesced_columns}))")
|
36
40
|
end
|
37
41
|
|
38
|
-
context 'searching by word_similarity' do
|
42
|
+
context 'when searching by word_similarity' do
|
39
43
|
let(:options) do
|
40
44
|
{ word_similarity: true }
|
41
45
|
end
|
@@ -46,7 +50,7 @@ describe PgSearch::Features::Trigram do
|
|
46
50
|
end
|
47
51
|
end
|
48
52
|
|
49
|
-
context 'ignoring accents' do
|
53
|
+
context 'when ignoring accents' do
|
50
54
|
it 'escapes the search document and query, but not the accent function' do
|
51
55
|
config.ignore = [:accents]
|
52
56
|
expect(feature.conditions.to_sql).to eq("(unaccent('#{query}') % (unaccent(#{coalesced_columns})))")
|
@@ -54,7 +58,7 @@ describe PgSearch::Features::Trigram do
|
|
54
58
|
end
|
55
59
|
|
56
60
|
context 'when a threshold is specified' do
|
57
|
-
context 'searching by similarity' do
|
61
|
+
context 'when searching by similarity' do
|
58
62
|
let(:options) do
|
59
63
|
{ threshold: 0.5 }
|
60
64
|
end
|
@@ -66,7 +70,7 @@ describe PgSearch::Features::Trigram do
|
|
66
70
|
end
|
67
71
|
end
|
68
72
|
|
69
|
-
context 'searching by word_similarity' do
|
73
|
+
context 'when searching by word_similarity' do
|
70
74
|
let(:options) do
|
71
75
|
{ threshold: 0.5, word_similarity: true }
|
72
76
|
end
|
@@ -79,21 +83,20 @@ describe PgSearch::Features::Trigram do
|
|
79
83
|
end
|
80
84
|
end
|
81
85
|
|
82
|
-
context 'only certain columns are selected' do
|
83
|
-
context 'one column' do
|
86
|
+
context 'when only certain columns are selected' do
|
87
|
+
context 'with one column' do
|
84
88
|
let(:options) { { only: :name } }
|
85
89
|
|
86
90
|
it 'only searches against the select column' do
|
87
|
-
options = { only: :name }
|
88
91
|
coalesced_column = "coalesce(#{Model.quoted_table_name}.\"name\"::text, '')"
|
89
92
|
expect(feature.conditions.to_sql).to eq("('#{query}' % (#{coalesced_column}))")
|
90
93
|
end
|
91
94
|
end
|
92
|
-
|
95
|
+
|
96
|
+
context 'with multiple columns' do
|
93
97
|
let(:options) { { only: %i[name content] } }
|
94
98
|
|
95
99
|
it 'concatenates when multiples columns are selected' do
|
96
|
-
options = { only: %i[name content] }
|
97
100
|
expect(feature.conditions.to_sql).to eq("('#{query}' % (#{coalesced_columns}))")
|
98
101
|
end
|
99
102
|
end
|
@@ -106,3 +109,4 @@ describe PgSearch::Features::Trigram do
|
|
106
109
|
end
|
107
110
|
end
|
108
111
|
end
|
112
|
+
# rubocop:enable RSpec/MultipleMemoizedHelpers, RSpec/NestedGroups
|
@@ -19,7 +19,7 @@ describe PgSearch::Features::TSearch do
|
|
19
19
|
PgSearch::Configuration::Column.new(:content, nil, Model)
|
20
20
|
]
|
21
21
|
options = {}
|
22
|
-
config =
|
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)
|
@@ -44,7 +44,7 @@ describe PgSearch::Features::TSearch do
|
|
44
44
|
PgSearch::Configuration::Column.new(:content, nil, Model)
|
45
45
|
]
|
46
46
|
options = {}
|
47
|
-
config =
|
47
|
+
config = instance_double("PgSearch::Configuration", :config, ignore: [])
|
48
48
|
normalizer = PgSearch::Normalizer.new(config)
|
49
49
|
|
50
50
|
feature = described_class.new(query, options, columns, Model, normalizer)
|
@@ -61,7 +61,7 @@ describe PgSearch::Features::TSearch do
|
|
61
61
|
PgSearch::Configuration::Column.new(:content, nil, Model)
|
62
62
|
]
|
63
63
|
options = { negation: true }
|
64
|
-
config =
|
64
|
+
config = instance_double("PgSearch::Configuration", :config, ignore: [])
|
65
65
|
normalizer = PgSearch::Normalizer.new(config)
|
66
66
|
|
67
67
|
feature = described_class.new(query, options, columns, Model, normalizer)
|
@@ -79,7 +79,7 @@ describe PgSearch::Features::TSearch do
|
|
79
79
|
PgSearch::Configuration::Column.new(:content, nil, Model)
|
80
80
|
]
|
81
81
|
options = { negation: false }
|
82
|
-
config =
|
82
|
+
config = instance_double("PgSearch::Configuration", :config, ignore: [])
|
83
83
|
normalizer = PgSearch::Normalizer.new(config)
|
84
84
|
|
85
85
|
feature = described_class.new(query, options, columns, Model, normalizer)
|
@@ -97,7 +97,7 @@ describe PgSearch::Features::TSearch do
|
|
97
97
|
PgSearch::Configuration::Column.new(:content, nil, Model)
|
98
98
|
]
|
99
99
|
options = { tsvector_column: "my_tsvector" }
|
100
|
-
config =
|
100
|
+
config = instance_double("PgSearch::Configuration", :config, ignore: [])
|
101
101
|
normalizer = PgSearch::Normalizer.new(config)
|
102
102
|
|
103
103
|
feature = described_class.new(query, options, columns, Model, normalizer)
|
@@ -115,7 +115,7 @@ describe PgSearch::Features::TSearch do
|
|
115
115
|
PgSearch::Configuration::Column.new(:content, nil, Model)
|
116
116
|
]
|
117
117
|
options = { tsvector_column: ["tsvector1", "tsvector2"] }
|
118
|
-
config =
|
118
|
+
config = instance_double("PgSearch::Configuration", :config, ignore: [])
|
119
119
|
normalizer = PgSearch::Normalizer.new(config)
|
120
120
|
|
121
121
|
feature = described_class.new(query, options, columns, Model, normalizer)
|
@@ -141,7 +141,7 @@ describe PgSearch::Features::TSearch do
|
|
141
141
|
]
|
142
142
|
options = {}
|
143
143
|
|
144
|
-
config =
|
144
|
+
config = instance_double("PgSearch::Configuration", :config, ignore: [])
|
145
145
|
normalizer = PgSearch::Normalizer.new(config)
|
146
146
|
|
147
147
|
feature = described_class.new(query, options, columns, Model, normalizer)
|
@@ -151,6 +151,7 @@ describe PgSearch::Features::TSearch do
|
|
151
151
|
end
|
152
152
|
|
153
153
|
context "when options[:dictionary] is passed" do
|
154
|
+
# rubocop:disable RSpec/ExampleLength
|
154
155
|
it 'uses the provided dictionary' do
|
155
156
|
query = "query"
|
156
157
|
columns = [
|
@@ -165,7 +166,7 @@ describe PgSearch::Features::TSearch do
|
|
165
166
|
}
|
166
167
|
}
|
167
168
|
|
168
|
-
config =
|
169
|
+
config = instance_double("PgSearch::Configuration", :config, ignore: [])
|
169
170
|
normalizer = PgSearch::Normalizer.new(config)
|
170
171
|
|
171
172
|
feature = described_class.new(query, options, columns, Model, normalizer)
|
@@ -174,9 +175,11 @@ describe PgSearch::Features::TSearch do
|
|
174
175
|
|
175
176
|
expect(feature.highlight.to_sql).to eq(expected_sql)
|
176
177
|
end
|
178
|
+
# rubocop:enable RSpec/ExampleLength
|
177
179
|
end
|
178
180
|
|
179
181
|
context "when options[:highlight] has options set" do
|
182
|
+
# rubocop:disable RSpec/ExampleLength
|
180
183
|
it "passes the options to ts_headline" do
|
181
184
|
query = "query"
|
182
185
|
columns = [
|
@@ -195,7 +198,7 @@ describe PgSearch::Features::TSearch do
|
|
195
198
|
}
|
196
199
|
}
|
197
200
|
|
198
|
-
config =
|
201
|
+
config = instance_double("PgSearch::Configuration", :config, ignore: [])
|
199
202
|
normalizer = PgSearch::Normalizer.new(config)
|
200
203
|
|
201
204
|
feature = described_class.new(query, options, columns, Model, normalizer)
|
@@ -204,7 +207,9 @@ describe PgSearch::Features::TSearch do
|
|
204
207
|
|
205
208
|
expect(feature.highlight.to_sql).to eq(expected_sql)
|
206
209
|
end
|
210
|
+
# rubocop:enable RSpec/ExampleLength
|
207
211
|
|
212
|
+
# rubocop:disable RSpec/ExampleLength
|
208
213
|
it "passes deprecated options to ts_headline" do
|
209
214
|
query = "query"
|
210
215
|
columns = [
|
@@ -223,7 +228,7 @@ describe PgSearch::Features::TSearch do
|
|
223
228
|
}
|
224
229
|
}
|
225
230
|
|
226
|
-
config =
|
231
|
+
config = instance_double("PgSearch::Configuration", :config, ignore: [])
|
227
232
|
normalizer = PgSearch::Normalizer.new(config)
|
228
233
|
|
229
234
|
feature = described_class.new(query, options, columns, Model, normalizer)
|
@@ -233,6 +238,7 @@ describe PgSearch::Features::TSearch do
|
|
233
238
|
|
234
239
|
expect(highlight_sql).to eq(expected_sql)
|
235
240
|
end
|
241
|
+
# rubocop:enable RSpec/ExampleLength
|
236
242
|
end
|
237
243
|
end
|
238
244
|
end
|
@@ -2,20 +2,16 @@
|
|
2
2
|
|
3
3
|
require "spec_helper"
|
4
4
|
|
5
|
-
|
6
|
-
(ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR >= 1) ||
|
7
|
-
(ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR == 0 && ActiveRecord::VERSION::TINY >= 1)
|
8
|
-
end
|
9
|
-
|
5
|
+
# rubocop:disable RSpec/NestedGroups
|
10
6
|
describe PgSearch::Multisearch::Rebuilder do
|
11
|
-
with_table "pg_search_documents",
|
7
|
+
with_table "pg_search_documents", &DOCUMENTS_SCHEMA
|
12
8
|
|
13
9
|
describe 'when initialized with a model that is not multisearchable' do
|
14
10
|
with_model :not_multisearchable
|
15
11
|
|
16
12
|
it 'raises an exception' do
|
17
13
|
expect {
|
18
|
-
|
14
|
+
described_class.new(NotMultisearchable)
|
19
15
|
}.to raise_exception(
|
20
16
|
PgSearch::Multisearch::ModelNotMultisearchable,
|
21
17
|
"NotMultisearchable is not multisearchable. See PgSearch::ClassMethods#multisearchable"
|
@@ -25,10 +21,10 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
25
21
|
|
26
22
|
describe "#rebuild" do
|
27
23
|
context "when the model defines .rebuild_pg_search_documents" do
|
28
|
-
context "
|
24
|
+
context "when multisearchable is not conditional" do
|
29
25
|
with_model :Model do
|
30
26
|
model do
|
31
|
-
include PgSearch
|
27
|
+
include PgSearch::Model
|
32
28
|
multisearchable
|
33
29
|
|
34
30
|
def rebuild_pg_search_documents
|
@@ -36,14 +32,18 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
36
32
|
end
|
37
33
|
end
|
38
34
|
|
39
|
-
it "
|
40
|
-
rebuilder =
|
41
|
-
|
42
|
-
|
35
|
+
it "calls .rebuild_pg_search_documents" do
|
36
|
+
rebuilder = described_class.new(Model)
|
37
|
+
|
38
|
+
without_partial_double_verification do
|
39
|
+
allow(Model).to receive(:rebuild_pg_search_documents)
|
40
|
+
rebuilder.rebuild
|
41
|
+
expect(Model).to have_received(:rebuild_pg_search_documents)
|
42
|
+
end
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
context "
|
46
|
+
context "when multisearchable is conditional" do
|
47
47
|
%i[if unless].each do |conditional_key|
|
48
48
|
context "via :#{conditional_key}" do
|
49
49
|
with_model :Model do
|
@@ -52,7 +52,7 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
52
52
|
end
|
53
53
|
|
54
54
|
model do
|
55
|
-
include PgSearch
|
55
|
+
include PgSearch::Model
|
56
56
|
multisearchable conditional_key => :active?
|
57
57
|
|
58
58
|
def rebuild_pg_search_documents
|
@@ -60,10 +60,14 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
-
it "
|
64
|
-
rebuilder =
|
65
|
-
|
66
|
-
|
63
|
+
it "calls .rebuild_pg_search_documents" do
|
64
|
+
rebuilder = described_class.new(Model)
|
65
|
+
|
66
|
+
without_partial_double_verification do
|
67
|
+
allow(Model).to receive(:rebuild_pg_search_documents)
|
68
|
+
rebuilder.rebuild
|
69
|
+
expect(Model).to have_received(:rebuild_pg_search_documents)
|
70
|
+
end
|
67
71
|
end
|
68
72
|
end
|
69
73
|
end
|
@@ -71,7 +75,7 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
71
75
|
end
|
72
76
|
|
73
77
|
context "when the model does not define .rebuild_pg_search_documents" do
|
74
|
-
context "
|
78
|
+
context "when multisearchable is not conditional" do
|
75
79
|
context "when :against only includes columns" do
|
76
80
|
with_model :Model do
|
77
81
|
table do |t|
|
@@ -79,13 +83,13 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
79
83
|
end
|
80
84
|
|
81
85
|
model do
|
82
|
-
include PgSearch
|
86
|
+
include PgSearch::Model
|
83
87
|
multisearchable against: :name
|
84
88
|
end
|
85
89
|
end
|
86
90
|
|
87
|
-
it "
|
88
|
-
rebuilder =
|
91
|
+
it "does not call :rebuild_pg_search_documents" do
|
92
|
+
rebuilder = described_class.new(Model)
|
89
93
|
|
90
94
|
# stub respond_to? to return false since should_not_receive defines the method
|
91
95
|
original_respond_to = Model.method(:respond_to?)
|
@@ -97,28 +101,28 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
97
101
|
end
|
98
102
|
end
|
99
103
|
|
100
|
-
|
101
|
-
|
104
|
+
without_partial_double_verification do
|
105
|
+
allow(Model).to receive(:rebuild_pg_search_documents)
|
106
|
+
rebuilder.rebuild
|
107
|
+
expect(Model).not_to have_received(:rebuild_pg_search_documents)
|
108
|
+
end
|
102
109
|
end
|
103
110
|
|
104
|
-
|
111
|
+
# rubocop:disable RSpec/ExampleLength
|
112
|
+
it "executes the default SQL" do
|
105
113
|
time = Time.utc(2001, 1, 1, 0, 0, 0)
|
106
|
-
rebuilder =
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
) AS content,
|
119
|
-
'#{expected_timestamp}' AS created_at,
|
120
|
-
'#{expected_timestamp}' AS updated_at
|
121
|
-
FROM #{Model.quoted_table_name}
|
114
|
+
rebuilder = described_class.new(Model, -> { time })
|
115
|
+
|
116
|
+
expected_sql = <<~SQL.squish
|
117
|
+
INSERT INTO "pg_search_documents" (searchable_type, searchable_id, content, created_at, updated_at)
|
118
|
+
SELECT 'Model' AS searchable_type,
|
119
|
+
#{Model.quoted_table_name}.#{Model.primary_key} AS searchable_id,
|
120
|
+
(
|
121
|
+
coalesce(#{Model.quoted_table_name}."name"::text, '')
|
122
|
+
) AS content,
|
123
|
+
'2001-01-01 00:00:00' AS created_at,
|
124
|
+
'2001-01-01 00:00:00' AS updated_at
|
125
|
+
FROM #{Model.quoted_table_name}
|
122
126
|
SQL
|
123
127
|
|
124
128
|
executed_sql = []
|
@@ -133,56 +137,54 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
133
137
|
expect(executed_sql.length).to eq(1)
|
134
138
|
expect(executed_sql.first.strip).to eq(expected_sql.strip)
|
135
139
|
end
|
140
|
+
# rubocop:enable RSpec/ExampleLength
|
136
141
|
|
137
|
-
context "
|
142
|
+
context "with a model with a camel case column" do
|
138
143
|
with_model :ModelWithCamelCaseColumn do
|
139
144
|
table do |t|
|
140
145
|
t.string :camelName
|
141
146
|
end
|
142
147
|
|
143
148
|
model do
|
144
|
-
include PgSearch
|
149
|
+
include PgSearch::Model
|
145
150
|
multisearchable against: :name
|
146
151
|
end
|
147
152
|
end
|
148
153
|
|
149
154
|
it "creates search document without PG error" do
|
150
155
|
time = Time.utc(2001, 1, 1, 0, 0, 0)
|
151
|
-
rebuilder =
|
156
|
+
rebuilder = described_class.new(Model, -> { time })
|
152
157
|
rebuilder.rebuild
|
153
158
|
end
|
154
159
|
end
|
155
160
|
|
156
|
-
context "
|
161
|
+
context "with a model with a non-standard primary key" do
|
157
162
|
with_model :ModelWithNonStandardPrimaryKey do
|
158
163
|
table primary_key: :non_standard_primary_key do |t|
|
159
164
|
t.string :name
|
160
165
|
end
|
161
166
|
|
162
167
|
model do
|
163
|
-
include PgSearch
|
168
|
+
include PgSearch::Model
|
164
169
|
multisearchable against: :name
|
165
170
|
end
|
166
171
|
end
|
167
172
|
|
173
|
+
# rubocop:disable RSpec/ExampleLength
|
168
174
|
it "generates SQL with the correct primary key" do
|
169
175
|
time = Time.utc(2001, 1, 1, 0, 0, 0)
|
170
|
-
rebuilder =
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
) AS content,
|
183
|
-
'#{expected_timestamp}' AS created_at,
|
184
|
-
'#{expected_timestamp}' AS updated_at
|
185
|
-
FROM #{ModelWithNonStandardPrimaryKey.quoted_table_name}
|
176
|
+
rebuilder = described_class.new(ModelWithNonStandardPrimaryKey, -> { time })
|
177
|
+
|
178
|
+
expected_sql = <<~SQL.squish
|
179
|
+
INSERT INTO "pg_search_documents" (searchable_type, searchable_id, content, created_at, updated_at)
|
180
|
+
SELECT 'ModelWithNonStandardPrimaryKey' AS searchable_type,
|
181
|
+
#{ModelWithNonStandardPrimaryKey.quoted_table_name}.non_standard_primary_key AS searchable_id,
|
182
|
+
(
|
183
|
+
coalesce(#{ModelWithNonStandardPrimaryKey.quoted_table_name}."name"::text, '')
|
184
|
+
) AS content,
|
185
|
+
'2001-01-01 00:00:00' AS created_at,
|
186
|
+
'2001-01-01 00:00:00' AS updated_at
|
187
|
+
FROM #{ModelWithNonStandardPrimaryKey.quoted_table_name}
|
186
188
|
SQL
|
187
189
|
|
188
190
|
executed_sql = []
|
@@ -197,6 +199,7 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
197
199
|
expect(executed_sql.length).to eq(1)
|
198
200
|
expect(executed_sql.first.strip).to eq(expected_sql.strip)
|
199
201
|
end
|
202
|
+
# rubocop:enable RSpec/ExampleLength
|
200
203
|
end
|
201
204
|
end
|
202
205
|
|
@@ -206,7 +209,7 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
206
209
|
end
|
207
210
|
|
208
211
|
model do
|
209
|
-
include PgSearch
|
212
|
+
include PgSearch::Model
|
210
213
|
multisearchable against: [:foo]
|
211
214
|
|
212
215
|
def foo
|
@@ -215,10 +218,11 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
215
218
|
end
|
216
219
|
end
|
217
220
|
|
221
|
+
# rubocop:disable RSpec/ExampleLength
|
218
222
|
it "calls update_pg_search_document on each record" do
|
219
223
|
record = Model.create!
|
220
224
|
|
221
|
-
rebuilder =
|
225
|
+
rebuilder = described_class.new(Model)
|
222
226
|
|
223
227
|
# stub respond_to? to return false since should_not_receive defines the method
|
224
228
|
original_respond_to = Model.method(:respond_to?)
|
@@ -229,16 +233,49 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
229
233
|
original_respond_to.call(method_name, *args)
|
230
234
|
end
|
231
235
|
end
|
232
|
-
expect(Model).not_to receive(:rebuild_pg_search_documents)
|
233
236
|
|
234
|
-
|
237
|
+
without_partial_double_verification do
|
238
|
+
allow(Model).to receive(:rebuild_pg_search_documents)
|
239
|
+
|
240
|
+
rebuilder.rebuild
|
241
|
+
|
242
|
+
expect(Model).not_to have_received(:rebuild_pg_search_documents)
|
243
|
+
end
|
235
244
|
|
236
245
|
expect(record.pg_search_document).to be_present
|
237
246
|
end
|
247
|
+
# rubocop:enable RSpec/ExampleLength
|
248
|
+
end
|
249
|
+
|
250
|
+
context "when only additional_attributes is set" do
|
251
|
+
with_model :Model do
|
252
|
+
table do |t|
|
253
|
+
t.string :name
|
254
|
+
end
|
255
|
+
|
256
|
+
model do
|
257
|
+
include PgSearch::Model
|
258
|
+
multisearchable against: :name,
|
259
|
+
additional_attributes: ->(obj) { { additional_attribute_column: "#{obj.class}::#{obj.id}" } }
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
it "calls update_pg_search_document on each record" do
|
264
|
+
record_1 = Model.create!(name: "record_1", id: 1)
|
265
|
+
record_2 = Model.create!(name: "record_2", id: 2)
|
266
|
+
|
267
|
+
PgSearch::Document.delete_all
|
268
|
+
|
269
|
+
rebuilder = described_class.new(Model)
|
270
|
+
rebuilder.rebuild
|
271
|
+
|
272
|
+
expect(record_1.reload.pg_search_document.additional_attribute_column).to eq("Model::1")
|
273
|
+
expect(record_2.reload.pg_search_document.additional_attribute_column).to eq("Model::2")
|
274
|
+
end
|
238
275
|
end
|
239
276
|
end
|
240
277
|
|
241
|
-
context "
|
278
|
+
context "when multisearchable is conditional" do
|
242
279
|
context "via :if" do
|
243
280
|
with_model :Model do
|
244
281
|
table do |t|
|
@@ -246,16 +283,17 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
246
283
|
end
|
247
284
|
|
248
285
|
model do
|
249
|
-
include PgSearch
|
286
|
+
include PgSearch::Model
|
250
287
|
multisearchable if: :active?
|
251
288
|
end
|
252
289
|
end
|
253
290
|
|
291
|
+
# rubocop:disable RSpec/ExampleLength
|
254
292
|
it "calls update_pg_search_document on each record" do
|
255
293
|
record_1 = Model.create!(active: true)
|
256
294
|
record_2 = Model.create!(active: false)
|
257
295
|
|
258
|
-
rebuilder =
|
296
|
+
rebuilder = described_class.new(Model)
|
259
297
|
|
260
298
|
# stub respond_to? to return false since should_not_receive defines the method
|
261
299
|
original_respond_to = Model.method(:respond_to?)
|
@@ -266,13 +304,17 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
266
304
|
original_respond_to.call(method_name, *args)
|
267
305
|
end
|
268
306
|
end
|
269
|
-
expect(Model).not_to receive(:rebuild_pg_search_documents)
|
270
307
|
|
271
|
-
|
308
|
+
without_partial_double_verification do
|
309
|
+
allow(Model).to receive(:rebuild_pg_search_documents)
|
310
|
+
rebuilder.rebuild
|
311
|
+
expect(Model).not_to have_received(:rebuild_pg_search_documents)
|
312
|
+
end
|
272
313
|
|
273
314
|
expect(record_1.pg_search_document).to be_present
|
274
315
|
expect(record_2.pg_search_document).not_to be_present
|
275
316
|
end
|
317
|
+
# rubocop:enable RSpec/ExampleLength
|
276
318
|
end
|
277
319
|
|
278
320
|
context "via :unless" do
|
@@ -282,16 +324,17 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
282
324
|
end
|
283
325
|
|
284
326
|
model do
|
285
|
-
include PgSearch
|
327
|
+
include PgSearch::Model
|
286
328
|
multisearchable unless: :inactive?
|
287
329
|
end
|
288
330
|
end
|
289
331
|
|
332
|
+
# rubocop:disable RSpec/ExampleLength
|
290
333
|
it "calls update_pg_search_document on each record" do
|
291
334
|
record_1 = Model.create!(inactive: true)
|
292
335
|
record_2 = Model.create!(inactive: false)
|
293
336
|
|
294
|
-
rebuilder =
|
337
|
+
rebuilder = described_class.new(Model)
|
295
338
|
|
296
339
|
# stub respond_to? to return false since should_not_receive defines the method
|
297
340
|
original_respond_to = Model.method(:respond_to?)
|
@@ -302,15 +345,20 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
302
345
|
original_respond_to.call(method_name, *args)
|
303
346
|
end
|
304
347
|
end
|
305
|
-
expect(Model).not_to receive(:rebuild_pg_search_documents)
|
306
348
|
|
307
|
-
|
349
|
+
without_partial_double_verification do
|
350
|
+
allow(Model).to receive(:rebuild_pg_search_documents)
|
351
|
+
rebuilder.rebuild
|
352
|
+
expect(Model).not_to have_received(:rebuild_pg_search_documents)
|
353
|
+
end
|
308
354
|
|
309
355
|
expect(record_1.pg_search_document).not_to be_present
|
310
356
|
expect(record_2.pg_search_document).to be_present
|
311
357
|
end
|
358
|
+
# rubocop:enable RSpec/ExampleLength
|
312
359
|
end
|
313
360
|
end
|
314
361
|
end
|
315
362
|
end
|
316
363
|
end
|
364
|
+
# rubocop:enable RSpec/NestedGroups
|