pg_search 2.1.2 → 2.3.6
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 +5 -5
- data/.codeclimate.yml +1 -0
- data/.editorconfig +10 -0
- data/.github/dependabot.yml +11 -0
- data/.github/workflows/ci.yml +75 -0
- data/.jrubyrc +1 -0
- data/.rubocop.yml +95 -10
- data/.travis.yml +26 -48
- data/CHANGELOG.md +179 -112
- data/CODE_OF_CONDUCT.md +76 -0
- data/CONTRIBUTING.md +5 -3
- data/Gemfile +6 -4
- data/LICENSE +1 -1
- data/README.md +307 -198
- data/Rakefile +7 -3
- data/lib/pg_search/configuration/association.rb +2 -0
- data/lib/pg_search/configuration/column.rb +2 -0
- data/lib/pg_search/configuration/foreign_column.rb +2 -0
- data/lib/pg_search/configuration.rb +20 -6
- data/lib/pg_search/document.rb +7 -5
- data/lib/pg_search/features/dmetaphone.rb +7 -7
- data/lib/pg_search/features/feature.rb +4 -2
- data/lib/pg_search/features/trigram.rb +31 -5
- data/lib/pg_search/features/tsearch.rb +18 -14
- data/lib/pg_search/features.rb +2 -0
- data/lib/pg_search/migration/dmetaphone_generator.rb +3 -1
- data/lib/pg_search/migration/generator.rb +4 -2
- data/lib/pg_search/migration/multisearch_generator.rb +2 -1
- 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 +3 -3
- data/lib/pg_search/model.rb +57 -0
- data/lib/pg_search/multisearch/rebuilder.rb +14 -6
- data/lib/pg_search/multisearch.rb +23 -6
- data/lib/pg_search/multisearchable.rb +10 -6
- data/lib/pg_search/normalizer.rb +2 -0
- data/lib/pg_search/railtie.rb +2 -0
- data/lib/pg_search/scope_options.rb +26 -49
- data/lib/pg_search/tasks.rb +5 -1
- data/lib/pg_search/version.rb +3 -1
- data/lib/pg_search.rb +17 -55
- data/pg_search.gemspec +19 -11
- data/spec/.rubocop.yml +2 -2
- data/spec/integration/.rubocop.yml +11 -0
- data/spec/integration/associations_spec.rb +125 -162
- data/spec/integration/deprecation_spec.rb +33 -0
- data/spec/integration/pagination_spec.rb +10 -8
- data/spec/integration/pg_search_spec.rb +359 -306
- data/spec/integration/single_table_inheritance_spec.rb +18 -17
- data/spec/lib/pg_search/configuration/association_spec.rb +17 -13
- data/spec/lib/pg_search/configuration/column_spec.rb +2 -0
- data/spec/lib/pg_search/configuration/foreign_column_spec.rb +6 -4
- data/spec/lib/pg_search/features/dmetaphone_spec.rb +6 -4
- data/spec/lib/pg_search/features/trigram_spec.rb +51 -20
- data/spec/lib/pg_search/features/tsearch_spec.rb +29 -21
- data/spec/lib/pg_search/multisearch/rebuilder_spec.rb +151 -85
- data/spec/lib/pg_search/multisearch_spec.rb +67 -37
- data/spec/lib/pg_search/multisearchable_spec.rb +217 -123
- data/spec/lib/pg_search/normalizer_spec.rb +14 -10
- data/spec/lib/pg_search_spec.rb +102 -89
- data/spec/spec_helper.rb +25 -6
- data/spec/support/database.rb +19 -21
- data/spec/support/with_model.rb +2 -0
- metadata +106 -29
- data/.autotest +0 -5
- data/.rubocop_todo.yml +0 -163
- data/Guardfile +0 -6
@@ -1,19 +1,17 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
(ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR >= 1) ||
|
5
|
-
(ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR == 0 && ActiveRecord::VERSION::TINY >= 1)
|
6
|
-
end
|
3
|
+
require "spec_helper"
|
7
4
|
|
5
|
+
# rubocop:disable RSpec/NestedGroups
|
8
6
|
describe PgSearch::Multisearch::Rebuilder do
|
9
|
-
with_table "pg_search_documents",
|
7
|
+
with_table "pg_search_documents", &DOCUMENTS_SCHEMA
|
10
8
|
|
11
|
-
describe 'when
|
9
|
+
describe 'when initialized with a model that is not multisearchable' do
|
12
10
|
with_model :not_multisearchable
|
13
11
|
|
14
12
|
it 'raises an exception' do
|
15
13
|
expect {
|
16
|
-
|
14
|
+
described_class.new(NotMultisearchable)
|
17
15
|
}.to raise_exception(
|
18
16
|
PgSearch::Multisearch::ModelNotMultisearchable,
|
19
17
|
"NotMultisearchable is not multisearchable. See PgSearch::ClassMethods#multisearchable"
|
@@ -23,10 +21,10 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
23
21
|
|
24
22
|
describe "#rebuild" do
|
25
23
|
context "when the model defines .rebuild_pg_search_documents" do
|
26
|
-
context "
|
24
|
+
context "when multisearchable is not conditional" do
|
27
25
|
with_model :Model do
|
28
26
|
model do
|
29
|
-
include PgSearch
|
27
|
+
include PgSearch::Model
|
30
28
|
multisearchable
|
31
29
|
|
32
30
|
def rebuild_pg_search_documents
|
@@ -34,14 +32,18 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
34
32
|
end
|
35
33
|
end
|
36
34
|
|
37
|
-
it "
|
38
|
-
rebuilder =
|
39
|
-
|
40
|
-
|
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
|
41
43
|
end
|
42
44
|
end
|
43
45
|
|
44
|
-
context "
|
46
|
+
context "when multisearchable is conditional" do
|
45
47
|
%i[if unless].each do |conditional_key|
|
46
48
|
context "via :#{conditional_key}" do
|
47
49
|
with_model :Model do
|
@@ -50,7 +52,7 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
50
52
|
end
|
51
53
|
|
52
54
|
model do
|
53
|
-
include PgSearch
|
55
|
+
include PgSearch::Model
|
54
56
|
multisearchable conditional_key => :active?
|
55
57
|
|
56
58
|
def rebuild_pg_search_documents
|
@@ -58,10 +60,14 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
58
60
|
end
|
59
61
|
end
|
60
62
|
|
61
|
-
it "
|
62
|
-
rebuilder =
|
63
|
-
|
64
|
-
|
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
|
65
71
|
end
|
66
72
|
end
|
67
73
|
end
|
@@ -69,7 +75,7 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
69
75
|
end
|
70
76
|
|
71
77
|
context "when the model does not define .rebuild_pg_search_documents" do
|
72
|
-
context "
|
78
|
+
context "when multisearchable is not conditional" do
|
73
79
|
context "when :against only includes columns" do
|
74
80
|
with_model :Model do
|
75
81
|
table do |t|
|
@@ -77,13 +83,13 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
77
83
|
end
|
78
84
|
|
79
85
|
model do
|
80
|
-
include PgSearch
|
81
|
-
multisearchable :
|
86
|
+
include PgSearch::Model
|
87
|
+
multisearchable against: :name
|
82
88
|
end
|
83
89
|
end
|
84
90
|
|
85
|
-
it "
|
86
|
-
rebuilder =
|
91
|
+
it "does not call :rebuild_pg_search_documents" do
|
92
|
+
rebuilder = described_class.new(Model)
|
87
93
|
|
88
94
|
# stub respond_to? to return false since should_not_receive defines the method
|
89
95
|
original_respond_to = Model.method(:respond_to?)
|
@@ -95,28 +101,28 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
95
101
|
end
|
96
102
|
end
|
97
103
|
|
98
|
-
|
99
|
-
|
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
|
100
109
|
end
|
101
110
|
|
102
|
-
|
111
|
+
# rubocop:disable RSpec/ExampleLength
|
112
|
+
it "executes the default SQL" do
|
103
113
|
time = Time.utc(2001, 1, 1, 0, 0, 0)
|
104
|
-
rebuilder =
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
) AS content,
|
117
|
-
'#{expected_timestamp}' AS created_at,
|
118
|
-
'#{expected_timestamp}' AS updated_at
|
119
|
-
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}
|
120
126
|
SQL
|
121
127
|
|
122
128
|
executed_sql = []
|
@@ -131,37 +137,54 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
131
137
|
expect(executed_sql.length).to eq(1)
|
132
138
|
expect(executed_sql.first.strip).to eq(expected_sql.strip)
|
133
139
|
end
|
140
|
+
# rubocop:enable RSpec/ExampleLength
|
134
141
|
|
135
|
-
context "
|
142
|
+
context "with a model with a camel case column" do
|
143
|
+
with_model :ModelWithCamelCaseColumn do
|
144
|
+
table do |t|
|
145
|
+
t.string :camelName
|
146
|
+
end
|
147
|
+
|
148
|
+
model do
|
149
|
+
include PgSearch::Model
|
150
|
+
multisearchable against: :name
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
it "creates search document without PG error" do
|
155
|
+
time = Time.utc(2001, 1, 1, 0, 0, 0)
|
156
|
+
rebuilder = described_class.new(Model, -> { time })
|
157
|
+
rebuilder.rebuild
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
context "with a model with a non-standard primary key" do
|
136
162
|
with_model :ModelWithNonStandardPrimaryKey do
|
137
163
|
table primary_key: :non_standard_primary_key do |t|
|
138
164
|
t.string :name
|
139
165
|
end
|
140
166
|
|
141
167
|
model do
|
142
|
-
include PgSearch
|
143
|
-
multisearchable :
|
168
|
+
include PgSearch::Model
|
169
|
+
multisearchable against: :name
|
144
170
|
end
|
145
171
|
end
|
146
172
|
|
173
|
+
# rubocop:disable RSpec/ExampleLength
|
147
174
|
it "generates SQL with the correct primary key" do
|
148
175
|
time = Time.utc(2001, 1, 1, 0, 0, 0)
|
149
|
-
rebuilder =
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
) AS content,
|
162
|
-
'#{expected_timestamp}' AS created_at,
|
163
|
-
'#{expected_timestamp}' AS updated_at
|
164
|
-
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}
|
165
188
|
SQL
|
166
189
|
|
167
190
|
executed_sql = []
|
@@ -176,16 +199,14 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
176
199
|
expect(executed_sql.length).to eq(1)
|
177
200
|
expect(executed_sql.first.strip).to eq(expected_sql.strip)
|
178
201
|
end
|
202
|
+
# rubocop:enable RSpec/ExampleLength
|
179
203
|
end
|
180
204
|
end
|
181
205
|
|
182
206
|
context "when :against includes non-column dynamic methods" do
|
183
207
|
with_model :Model do
|
184
|
-
table do
|
185
|
-
end
|
186
|
-
|
187
208
|
model do
|
188
|
-
include PgSearch
|
209
|
+
include PgSearch::Model
|
189
210
|
multisearchable against: [:foo]
|
190
211
|
|
191
212
|
def foo
|
@@ -194,10 +215,11 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
194
215
|
end
|
195
216
|
end
|
196
217
|
|
218
|
+
# rubocop:disable RSpec/ExampleLength
|
197
219
|
it "calls update_pg_search_document on each record" do
|
198
220
|
record = Model.create!
|
199
221
|
|
200
|
-
rebuilder =
|
222
|
+
rebuilder = described_class.new(Model)
|
201
223
|
|
202
224
|
# stub respond_to? to return false since should_not_receive defines the method
|
203
225
|
original_respond_to = Model.method(:respond_to?)
|
@@ -208,16 +230,49 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
208
230
|
original_respond_to.call(method_name, *args)
|
209
231
|
end
|
210
232
|
end
|
211
|
-
expect(Model).not_to receive(:rebuild_pg_search_documents)
|
212
233
|
|
213
|
-
|
234
|
+
without_partial_double_verification do
|
235
|
+
allow(Model).to receive(:rebuild_pg_search_documents)
|
236
|
+
|
237
|
+
rebuilder.rebuild
|
238
|
+
|
239
|
+
expect(Model).not_to have_received(:rebuild_pg_search_documents)
|
240
|
+
end
|
214
241
|
|
215
242
|
expect(record.pg_search_document).to be_present
|
216
243
|
end
|
244
|
+
# rubocop:enable RSpec/ExampleLength
|
245
|
+
end
|
246
|
+
|
247
|
+
context "when only additional_attributes is set" do
|
248
|
+
with_model :Model do
|
249
|
+
table do |t|
|
250
|
+
t.string :name
|
251
|
+
end
|
252
|
+
|
253
|
+
model do
|
254
|
+
include PgSearch::Model
|
255
|
+
multisearchable against: :name,
|
256
|
+
additional_attributes: ->(obj) { { additional_attribute_column: "#{obj.class}::#{obj.id}" } }
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
it "calls update_pg_search_document on each record" do
|
261
|
+
record_1 = Model.create!(name: "record_1", id: 1)
|
262
|
+
record_2 = Model.create!(name: "record_2", id: 2)
|
263
|
+
|
264
|
+
PgSearch::Document.delete_all
|
265
|
+
|
266
|
+
rebuilder = described_class.new(Model)
|
267
|
+
rebuilder.rebuild
|
268
|
+
|
269
|
+
expect(record_1.reload.pg_search_document.additional_attribute_column).to eq("Model::1")
|
270
|
+
expect(record_2.reload.pg_search_document.additional_attribute_column).to eq("Model::2")
|
271
|
+
end
|
217
272
|
end
|
218
273
|
end
|
219
274
|
|
220
|
-
context "
|
275
|
+
context "when multisearchable is conditional" do
|
221
276
|
context "via :if" do
|
222
277
|
with_model :Model do
|
223
278
|
table do |t|
|
@@ -225,16 +280,17 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
225
280
|
end
|
226
281
|
|
227
282
|
model do
|
228
|
-
include PgSearch
|
229
|
-
multisearchable :
|
283
|
+
include PgSearch::Model
|
284
|
+
multisearchable if: :active?
|
230
285
|
end
|
231
286
|
end
|
232
287
|
|
288
|
+
# rubocop:disable RSpec/ExampleLength
|
233
289
|
it "calls update_pg_search_document on each record" do
|
234
|
-
record_1 = Model.create!(:
|
235
|
-
record_2 = Model.create!(:
|
290
|
+
record_1 = Model.create!(active: true)
|
291
|
+
record_2 = Model.create!(active: false)
|
236
292
|
|
237
|
-
rebuilder =
|
293
|
+
rebuilder = described_class.new(Model)
|
238
294
|
|
239
295
|
# stub respond_to? to return false since should_not_receive defines the method
|
240
296
|
original_respond_to = Model.method(:respond_to?)
|
@@ -245,13 +301,17 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
245
301
|
original_respond_to.call(method_name, *args)
|
246
302
|
end
|
247
303
|
end
|
248
|
-
expect(Model).not_to receive(:rebuild_pg_search_documents)
|
249
304
|
|
250
|
-
|
305
|
+
without_partial_double_verification do
|
306
|
+
allow(Model).to receive(:rebuild_pg_search_documents)
|
307
|
+
rebuilder.rebuild
|
308
|
+
expect(Model).not_to have_received(:rebuild_pg_search_documents)
|
309
|
+
end
|
251
310
|
|
252
311
|
expect(record_1.pg_search_document).to be_present
|
253
312
|
expect(record_2.pg_search_document).not_to be_present
|
254
313
|
end
|
314
|
+
# rubocop:enable RSpec/ExampleLength
|
255
315
|
end
|
256
316
|
|
257
317
|
context "via :unless" do
|
@@ -261,16 +321,17 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
261
321
|
end
|
262
322
|
|
263
323
|
model do
|
264
|
-
include PgSearch
|
265
|
-
multisearchable :
|
324
|
+
include PgSearch::Model
|
325
|
+
multisearchable unless: :inactive?
|
266
326
|
end
|
267
327
|
end
|
268
328
|
|
329
|
+
# rubocop:disable RSpec/ExampleLength
|
269
330
|
it "calls update_pg_search_document on each record" do
|
270
|
-
record_1 = Model.create!(:
|
271
|
-
record_2 = Model.create!(:
|
331
|
+
record_1 = Model.create!(inactive: true)
|
332
|
+
record_2 = Model.create!(inactive: false)
|
272
333
|
|
273
|
-
rebuilder =
|
334
|
+
rebuilder = described_class.new(Model)
|
274
335
|
|
275
336
|
# stub respond_to? to return false since should_not_receive defines the method
|
276
337
|
original_respond_to = Model.method(:respond_to?)
|
@@ -281,15 +342,20 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
281
342
|
original_respond_to.call(method_name, *args)
|
282
343
|
end
|
283
344
|
end
|
284
|
-
expect(Model).not_to receive(:rebuild_pg_search_documents)
|
285
345
|
|
286
|
-
|
346
|
+
without_partial_double_verification do
|
347
|
+
allow(Model).to receive(:rebuild_pg_search_documents)
|
348
|
+
rebuilder.rebuild
|
349
|
+
expect(Model).not_to have_received(:rebuild_pg_search_documents)
|
350
|
+
end
|
287
351
|
|
288
352
|
expect(record_1.pg_search_document).not_to be_present
|
289
353
|
expect(record_2.pg_search_document).to be_present
|
290
354
|
end
|
355
|
+
# rubocop:enable RSpec/ExampleLength
|
291
356
|
end
|
292
357
|
end
|
293
358
|
end
|
294
359
|
end
|
295
360
|
end
|
361
|
+
# rubocop:enable RSpec/NestedGroups
|
@@ -1,7 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "spec_helper"
|
4
|
+
require "active_support/deprecation"
|
2
5
|
|
6
|
+
# rubocop:disable RSpec/NestedGroups
|
3
7
|
describe PgSearch::Multisearch do
|
4
|
-
with_table "pg_search_documents",
|
8
|
+
with_table "pg_search_documents", &DOCUMENTS_SCHEMA
|
5
9
|
|
6
10
|
with_model :MultisearchableModel do
|
7
11
|
table do |t|
|
@@ -10,28 +14,37 @@ describe PgSearch::Multisearch do
|
|
10
14
|
t.timestamps null: false
|
11
15
|
end
|
12
16
|
model do
|
13
|
-
include PgSearch
|
17
|
+
include PgSearch::Model
|
14
18
|
end
|
15
19
|
end
|
16
20
|
|
17
21
|
let(:model) { MultisearchableModel }
|
18
22
|
let(:connection) { model.connection }
|
19
|
-
let(:documents) { double(:documents) }
|
20
23
|
|
21
24
|
describe ".rebuild" do
|
22
25
|
before do
|
23
|
-
model.multisearchable :
|
26
|
+
model.multisearchable against: :title
|
24
27
|
end
|
25
28
|
|
26
|
-
it "
|
27
|
-
|
29
|
+
it "operates inside a transaction" do
|
30
|
+
allow(model).to receive(:transaction)
|
31
|
+
|
32
|
+
described_class.rebuild(model)
|
33
|
+
expect(model).to have_received(:transaction).once
|
34
|
+
end
|
28
35
|
|
29
|
-
|
36
|
+
context "when transactional is false" do
|
37
|
+
it "does not operate inside a transaction" do
|
38
|
+
allow(model).to receive(:transaction)
|
39
|
+
|
40
|
+
described_class.rebuild(model, transactional: false)
|
41
|
+
expect(model).not_to have_received(:transaction)
|
42
|
+
end
|
30
43
|
end
|
31
44
|
|
32
45
|
describe "cleaning up search documents for this model" do
|
33
46
|
before do
|
34
|
-
connection.execute
|
47
|
+
connection.execute <<~SQL.squish
|
35
48
|
INSERT INTO pg_search_documents
|
36
49
|
(searchable_type, searchable_id, content, created_at, updated_at)
|
37
50
|
VALUES
|
@@ -45,28 +58,39 @@ describe PgSearch::Multisearch do
|
|
45
58
|
end
|
46
59
|
|
47
60
|
context "when clean_up is not passed" do
|
48
|
-
it "
|
49
|
-
|
61
|
+
it "deletes the document for the model" do
|
62
|
+
described_class.rebuild(model)
|
50
63
|
expect(PgSearch::Document.count).to eq(1)
|
51
64
|
expect(PgSearch::Document.first.searchable_type).to eq("Bar")
|
52
65
|
end
|
53
66
|
end
|
54
67
|
|
55
68
|
context "when clean_up is true" do
|
56
|
-
|
57
|
-
|
58
|
-
it "should delete the document for the model" do
|
59
|
-
PgSearch::Multisearch.rebuild(model, clean_up)
|
69
|
+
it "deletes the document for the model" do
|
70
|
+
described_class.rebuild(model, clean_up: true)
|
60
71
|
expect(PgSearch::Document.count).to eq(1)
|
61
72
|
expect(PgSearch::Document.first.searchable_type).to eq("Bar")
|
62
73
|
end
|
63
74
|
end
|
64
75
|
|
65
76
|
context "when clean_up is false" do
|
66
|
-
|
77
|
+
it "does not delete the document for the model" do
|
78
|
+
described_class.rebuild(model, clean_up: false)
|
79
|
+
expect(PgSearch::Document.count).to eq(2)
|
80
|
+
end
|
81
|
+
end
|
67
82
|
|
68
|
-
|
69
|
-
|
83
|
+
context "when deprecated_clean_up is true" do
|
84
|
+
it "deletes the document for the model" do
|
85
|
+
ActiveSupport::Deprecation.silence { described_class.rebuild(model, true) }
|
86
|
+
expect(PgSearch::Document.count).to eq(1)
|
87
|
+
expect(PgSearch::Document.first.searchable_type).to eq("Bar")
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context "when deprecated_clean_up is false" do
|
92
|
+
it "does not delete the document for the model" do
|
93
|
+
ActiveSupport::Deprecation.silence { described_class.rebuild(model, false) }
|
70
94
|
expect(PgSearch::Document.count).to eq(2)
|
71
95
|
end
|
72
96
|
end
|
@@ -74,7 +98,7 @@ describe PgSearch::Multisearch do
|
|
74
98
|
context "when the model implements .rebuild_pg_search_documents" do
|
75
99
|
before do
|
76
100
|
def model.rebuild_pg_search_documents
|
77
|
-
connection.execute
|
101
|
+
connection.execute <<~SQL.squish
|
78
102
|
INSERT INTO pg_search_documents
|
79
103
|
(searchable_type, searchable_id, content, created_at, updated_at)
|
80
104
|
VALUES
|
@@ -83,45 +107,50 @@ describe PgSearch::Multisearch do
|
|
83
107
|
end
|
84
108
|
end
|
85
109
|
|
86
|
-
it "
|
87
|
-
|
88
|
-
|
110
|
+
it "calls .rebuild_pg_search_documents and skips the default behavior" do
|
111
|
+
without_partial_double_verification do
|
112
|
+
allow(model).to receive(:rebuild_sql)
|
113
|
+
described_class.rebuild(model)
|
89
114
|
|
90
|
-
|
91
|
-
|
115
|
+
record = PgSearch::Document.find_by(searchable_type: "Baz", searchable_id: 789)
|
116
|
+
expect(model).not_to have_received(:rebuild_sql)
|
117
|
+
expect(record.content).to eq("baz")
|
118
|
+
end
|
92
119
|
end
|
93
120
|
end
|
94
121
|
end
|
95
122
|
|
96
123
|
describe "inserting the new documents" do
|
97
124
|
let!(:new_models) { [] }
|
125
|
+
|
98
126
|
before do
|
99
|
-
new_models << model.create!(:
|
100
|
-
new_models << model.create!(:
|
127
|
+
new_models << model.create!(title: "Foo", content: "Bar")
|
128
|
+
new_models << model.create!(title: "Baz", content: "Bar")
|
101
129
|
end
|
102
130
|
|
103
|
-
it "
|
104
|
-
|
131
|
+
it "creates new documents for the two models" do
|
132
|
+
described_class.rebuild(model)
|
105
133
|
expect(PgSearch::Document.last(2).map(&:searchable).map(&:title)).to match_array(new_models.map(&:title))
|
106
134
|
end
|
107
135
|
end
|
108
136
|
|
109
137
|
describe "the generated SQL" do
|
110
138
|
let(:now) { Time.now }
|
139
|
+
|
111
140
|
before { allow(Time).to receive(:now).and_return(now) }
|
112
141
|
|
113
142
|
context "with one attribute" do
|
114
143
|
before do
|
115
|
-
model.multisearchable :
|
144
|
+
model.multisearchable against: [:title]
|
116
145
|
end
|
117
146
|
|
118
|
-
it "
|
119
|
-
expected_sql =
|
147
|
+
it "generates the proper SQL code" do
|
148
|
+
expected_sql = <<~SQL.squish
|
120
149
|
INSERT INTO #{PgSearch::Document.quoted_table_name} (searchable_type, searchable_id, content, created_at, updated_at)
|
121
150
|
SELECT #{connection.quote(model.name)} AS searchable_type,
|
122
151
|
#{model.quoted_table_name}.id AS searchable_id,
|
123
152
|
(
|
124
|
-
coalesce(#{model.quoted_table_name}.title::text, '')
|
153
|
+
coalesce(#{model.quoted_table_name}."title"::text, '')
|
125
154
|
) AS content,
|
126
155
|
#{connection.quote(connection.quoted_date(now))} AS created_at,
|
127
156
|
#{connection.quote(connection.quoted_date(now))} AS updated_at
|
@@ -131,7 +160,7 @@ describe PgSearch::Multisearch do
|
|
131
160
|
statements = []
|
132
161
|
allow(connection).to receive(:execute) { |sql| statements << sql.strip }
|
133
162
|
|
134
|
-
|
163
|
+
described_class.rebuild(model)
|
135
164
|
|
136
165
|
expect(statements).to include(expected_sql.strip)
|
137
166
|
end
|
@@ -139,16 +168,16 @@ describe PgSearch::Multisearch do
|
|
139
168
|
|
140
169
|
context "with multiple attributes" do
|
141
170
|
before do
|
142
|
-
model.multisearchable :
|
171
|
+
model.multisearchable against: %i[title content]
|
143
172
|
end
|
144
173
|
|
145
|
-
it "
|
146
|
-
expected_sql =
|
174
|
+
it "generates the proper SQL code" do
|
175
|
+
expected_sql = <<~SQL.squish
|
147
176
|
INSERT INTO #{PgSearch::Document.quoted_table_name} (searchable_type, searchable_id, content, created_at, updated_at)
|
148
177
|
SELECT #{connection.quote(model.name)} AS searchable_type,
|
149
178
|
#{model.quoted_table_name}.id AS searchable_id,
|
150
179
|
(
|
151
|
-
coalesce(#{model.quoted_table_name}.title::text, '') || ' ' || coalesce(#{model.quoted_table_name}.content::text, '')
|
180
|
+
coalesce(#{model.quoted_table_name}."title"::text, '') || ' ' || coalesce(#{model.quoted_table_name}."content"::text, '')
|
152
181
|
) AS content,
|
153
182
|
#{connection.quote(connection.quoted_date(now))} AS created_at,
|
154
183
|
#{connection.quote(connection.quoted_date(now))} AS updated_at
|
@@ -158,7 +187,7 @@ describe PgSearch::Multisearch do
|
|
158
187
|
statements = []
|
159
188
|
allow(connection).to receive(:execute) { |sql| statements << sql.strip }
|
160
189
|
|
161
|
-
|
190
|
+
described_class.rebuild(model)
|
162
191
|
|
163
192
|
expect(statements).to include(expected_sql.strip)
|
164
193
|
end
|
@@ -166,3 +195,4 @@ describe PgSearch::Multisearch do
|
|
166
195
|
end
|
167
196
|
end
|
168
197
|
end
|
198
|
+
# rubocop:enable RSpec/NestedGroups
|