pg_search 2.3.6 → 2.3.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +21 -16
  3. data/.standard.yml +6 -0
  4. data/CHANGELOG.md +11 -0
  5. data/Gemfile +19 -6
  6. data/LICENSE +1 -1
  7. data/README.md +49 -32
  8. data/Rakefile +4 -7
  9. data/lib/pg_search/configuration/column.rb +6 -4
  10. data/lib/pg_search/configuration/foreign_column.rb +1 -1
  11. data/lib/pg_search/configuration.rb +1 -1
  12. data/lib/pg_search/document.rb +8 -8
  13. data/lib/pg_search/features/dmetaphone.rb +1 -1
  14. data/lib/pg_search/features/trigram.rb +4 -4
  15. data/lib/pg_search/features/tsearch.rb +14 -13
  16. data/lib/pg_search/migration/dmetaphone_generator.rb +2 -2
  17. data/lib/pg_search/migration/generator.rb +5 -5
  18. data/lib/pg_search/migration/multisearch_generator.rb +2 -2
  19. data/lib/pg_search/model.rb +6 -6
  20. data/lib/pg_search/multisearch.rb +4 -2
  21. data/lib/pg_search/multisearchable.rb +7 -7
  22. data/lib/pg_search/normalizer.rb +5 -5
  23. data/lib/pg_search/scope_options.rb +26 -5
  24. data/lib/pg_search/tasks.rb +2 -2
  25. data/lib/pg_search/version.rb +1 -1
  26. data/lib/pg_search.rb +3 -3
  27. data/pg_search.gemspec +16 -31
  28. data/spec/.rubocop.yml +20 -7
  29. data/spec/integration/.rubocop.yml +2 -2
  30. data/spec/integration/associations_spec.rb +106 -106
  31. data/spec/integration/deprecation_spec.rb +7 -8
  32. data/spec/integration/pg_search_spec.rb +314 -298
  33. data/spec/integration/single_table_inheritance_spec.rb +5 -5
  34. data/spec/lib/pg_search/configuration/association_spec.rb +15 -15
  35. data/spec/lib/pg_search/configuration/column_spec.rb +13 -1
  36. data/spec/lib/pg_search/configuration/foreign_column_spec.rb +4 -4
  37. data/spec/lib/pg_search/features/dmetaphone_spec.rb +4 -4
  38. data/spec/lib/pg_search/features/trigram_spec.rb +29 -29
  39. data/spec/lib/pg_search/features/tsearch_spec.rb +57 -39
  40. data/spec/lib/pg_search/multisearch/rebuilder_spec.rb +17 -17
  41. data/spec/lib/pg_search/multisearch_spec.rb +6 -6
  42. data/spec/lib/pg_search/multisearchable_spec.rb +26 -26
  43. data/spec/lib/pg_search/normalizer_spec.rb +7 -7
  44. data/spec/lib/pg_search_spec.rb +18 -18
  45. data/spec/spec_helper.rb +7 -9
  46. data/spec/support/database.rb +6 -6
  47. metadata +10 -214
  48. data/.codeclimate.yml +0 -17
  49. data/.rubocop.yml +0 -137
  50. data/.travis.yml +0 -37
@@ -2,14 +2,14 @@
2
2
 
3
3
  require "spec_helper"
4
4
 
5
- # rubocop:disable RSpec/NestedGroups
5
+ # standard:disable RSpec/NestedGroups
6
6
  describe "an Active Record model which includes PgSearch" do
7
7
  with_model :ModelWithPgSearch do
8
8
  table do |t|
9
- t.string 'title'
10
- t.text 'content'
11
- t.integer 'parent_model_id'
12
- t.integer 'importance'
9
+ t.string "title"
10
+ t.text "content"
11
+ t.integer "parent_model_id"
12
+ t.integer "importance"
13
13
  end
14
14
 
15
15
  model do
@@ -39,26 +39,38 @@ describe "an Active Record model which includes PgSearch" do
39
39
  context "when passed a lambda" do
40
40
  it "builds a dynamic scope" do
41
41
  ModelWithPgSearch.pg_search_scope :search_title_or_content,
42
- lambda { |query, pick_content|
43
- {
44
- query: query.gsub("-remove-", ""),
45
- against: pick_content ? :content : :title
46
- }
47
- }
42
+ lambda { |query, pick_content|
43
+ {
44
+ query: query.gsub("-remove-", ""),
45
+ against: pick_content ? :content : :title
46
+ }
47
+ }
48
48
 
49
- included = ModelWithPgSearch.create!(title: 'foo', content: 'bar')
50
- excluded = ModelWithPgSearch.create!(title: 'bar', content: 'foo')
49
+ included = ModelWithPgSearch.create!(title: "foo", content: "bar")
50
+ ModelWithPgSearch.create!(title: "bar", content: "foo")
51
51
 
52
- expect(ModelWithPgSearch.search_title_or_content('fo-remove-o', false)).to eq([included])
53
- expect(ModelWithPgSearch.search_title_or_content('b-remove-ar', true)).to eq([included])
52
+ expect(ModelWithPgSearch.search_title_or_content("fo-remove-o", false)).to eq([included])
53
+ expect(ModelWithPgSearch.search_title_or_content("b-remove-ar", true)).to eq([included])
54
+ end
55
+ end
56
+
57
+ context "when passed an invalid argument" do
58
+ it "builds a dynamic scope" do
59
+ expect {
60
+ ModelWithPgSearch.pg_search_scope :search_title_or_content, :some_symbol
61
+ }.to(
62
+ raise_exception(ArgumentError).with_message(
63
+ "pg_search_scope expects a Hash or Proc"
64
+ )
65
+ )
54
66
  end
55
67
  end
56
68
 
57
69
  context "when an unknown option is passed in" do
58
70
  it "raises an exception when invoked" do
59
71
  ModelWithPgSearch.pg_search_scope :with_unknown_option,
60
- against: :content,
61
- foo: :bar
72
+ against: :content,
73
+ foo: :bar
62
74
 
63
75
  expect {
64
76
  ModelWithPgSearch.with_unknown_option("foo")
@@ -68,7 +80,7 @@ describe "an Active Record model which includes PgSearch" do
68
80
  context "with a lambda" do
69
81
  it "raises an exception when invoked" do
70
82
  ModelWithPgSearch.pg_search_scope :with_unknown_option,
71
- ->(*) { { against: :content, foo: :bar } }
83
+ ->(*) { {against: :content, foo: :bar} }
72
84
 
73
85
  expect {
74
86
  ModelWithPgSearch.with_unknown_option("foo")
@@ -80,8 +92,8 @@ describe "an Active Record model which includes PgSearch" do
80
92
  context "when an unknown :using is passed" do
81
93
  it "raises an exception when invoked" do
82
94
  ModelWithPgSearch.pg_search_scope :with_unknown_using,
83
- against: :content,
84
- using: :foo
95
+ against: :content,
96
+ using: :foo
85
97
 
86
98
  expect {
87
99
  ModelWithPgSearch.with_unknown_using("foo")
@@ -91,7 +103,7 @@ describe "an Active Record model which includes PgSearch" do
91
103
  context "with a lambda" do
92
104
  it "raises an exception when invoked" do
93
105
  ModelWithPgSearch.pg_search_scope :with_unknown_using,
94
- ->(*) { { against: :content, using: :foo } }
106
+ ->(*) { {against: :content, using: :foo} }
95
107
 
96
108
  expect {
97
109
  ModelWithPgSearch.with_unknown_using("foo")
@@ -103,8 +115,8 @@ describe "an Active Record model which includes PgSearch" do
103
115
  context "when an unknown :ignoring is passed" do
104
116
  it "raises an exception when invoked" do
105
117
  ModelWithPgSearch.pg_search_scope :with_unknown_ignoring,
106
- against: :content,
107
- ignoring: :foo
118
+ against: :content,
119
+ ignoring: :foo
108
120
 
109
121
  expect {
110
122
  ModelWithPgSearch.with_unknown_ignoring("foo")
@@ -114,7 +126,7 @@ describe "an Active Record model which includes PgSearch" do
114
126
  context "with a lambda" do
115
127
  it "raises an exception when invoked" do
116
128
  ModelWithPgSearch.pg_search_scope :with_unknown_ignoring,
117
- ->(*) { { against: :content, ignoring: :foo } }
129
+ ->(*) { {against: :content, ignoring: :foo} }
118
130
 
119
131
  expect {
120
132
  ModelWithPgSearch.with_unknown_ignoring("foo")
@@ -168,15 +180,15 @@ describe "an Active Record model which includes PgSearch" do
168
180
 
169
181
  context "when chained after a select() scope" do
170
182
  it "honors the select" do
171
- included = ModelWithPgSearch.create!(content: 'foo', title: 'bar')
172
- excluded = ModelWithPgSearch.create!(content: 'bar', title: 'foo')
183
+ included = ModelWithPgSearch.create!(content: "foo", title: "bar")
184
+ excluded = ModelWithPgSearch.create!(content: "bar", title: "foo")
173
185
 
174
- results = ModelWithPgSearch.select('id, title').search_content('foo')
186
+ results = ModelWithPgSearch.select("id, title").search_content("foo")
175
187
 
176
188
  expect(results).to include(included)
177
189
  expect(results).not_to include(excluded)
178
190
 
179
- expect(results.first.attributes.key?('content')).to eq false
191
+ expect(results.first.attributes.key?("content")).to be false
180
192
 
181
193
  expect(results.select { |record| record.title == "bar" }).to eq [included]
182
194
  expect(results.reject { |record| record.title == "bar" }).to be_empty
@@ -185,15 +197,15 @@ describe "an Active Record model which includes PgSearch" do
185
197
 
186
198
  context "when chained before a select() scope" do
187
199
  it "honors the select" do
188
- included = ModelWithPgSearch.create!(content: 'foo', title: 'bar')
189
- excluded = ModelWithPgSearch.create!(content: 'bar', title: 'foo')
200
+ included = ModelWithPgSearch.create!(content: "foo", title: "bar")
201
+ excluded = ModelWithPgSearch.create!(content: "bar", title: "foo")
190
202
 
191
- results = ModelWithPgSearch.search_content('foo').select('id, title')
203
+ results = ModelWithPgSearch.search_content("foo").select("id, title")
192
204
 
193
205
  expect(results).to include(included)
194
206
  expect(results).not_to include(excluded)
195
207
 
196
- expect(results.first.attributes.key?('content')).to eq false
208
+ expect(results.first.attributes.key?("content")).to be false
197
209
 
198
210
  expect(results.select { |record| record.title == "bar" }).to eq [included]
199
211
  expect(results.reject { |record| record.title == "bar" }).to be_empty
@@ -202,15 +214,15 @@ describe "an Active Record model which includes PgSearch" do
202
214
 
203
215
  context "when surrouned by select() scopes" do
204
216
  it "honors the select" do
205
- included = ModelWithPgSearch.create!(content: 'foo', title: 'bar')
206
- excluded = ModelWithPgSearch.create!(content: 'bar', title: 'foo')
217
+ included = ModelWithPgSearch.create!(content: "foo", title: "bar")
218
+ excluded = ModelWithPgSearch.create!(content: "bar", title: "foo")
207
219
 
208
- results = ModelWithPgSearch.select('id').search_content('foo').select('title')
220
+ results = ModelWithPgSearch.select("id").search_content("foo").select("title")
209
221
 
210
222
  expect(results).to include(included)
211
223
  expect(results).not_to include(excluded)
212
224
 
213
- expect(results.first.attributes.key?('content')).to eq false
225
+ expect(results.first.attributes.key?("content")).to be false
214
226
 
215
227
  expect(results.select { |record| record.title == "bar" }).to eq [included]
216
228
  expect(results.reject { |record| record.title == "bar" }).to be_empty
@@ -241,7 +253,7 @@ describe "an Active Record model which includes PgSearch" do
241
253
  has_many :houses
242
254
  pg_search_scope :named, against: [:name]
243
255
  scope :with_house_in_city, lambda { |city|
244
- joins(:houses).where(House.table_name.to_sym => { city: city })
256
+ joins(:houses).where(House.table_name.to_sym => {city: city})
245
257
  }
246
258
  scope :house_search_city, lambda { |query|
247
259
  joins(:houses).merge(House.search_city(query))
@@ -285,7 +297,7 @@ describe "an Active Record model which includes PgSearch" do
285
297
 
286
298
  context "when chaining merged scopes" do
287
299
  it "does not raise an exception" do
288
- relation = Person.named('foo').house_search_city('bar')
300
+ relation = Person.named("foo").house_search_city("bar")
289
301
 
290
302
  expect { relation.to_a }.not_to raise_error
291
303
  end
@@ -298,49 +310,49 @@ describe "an Active Record model which includes PgSearch" do
298
310
  end
299
311
 
300
312
  it "does not raise an exception" do
301
- relation = ModelWithPgSearch.search_content('foo').search_title('bar')
313
+ relation = ModelWithPgSearch.search_content("foo").search_title("bar")
302
314
 
303
315
  expect { relation.to_a }.not_to raise_error
304
316
  end
305
317
  end
306
318
 
307
319
  it "returns an empty array when a blank query is passed in" do
308
- ModelWithPgSearch.create!(content: 'foo')
320
+ ModelWithPgSearch.create!(content: "foo")
309
321
 
310
- results = ModelWithPgSearch.search_content('')
322
+ results = ModelWithPgSearch.search_content("")
311
323
  expect(results).to eq([])
312
324
  end
313
325
 
314
326
  it "returns rows where the column contains the term in the query" do
315
- included = ModelWithPgSearch.create!(content: 'foo')
316
- excluded = ModelWithPgSearch.create!(content: 'bar')
327
+ included = ModelWithPgSearch.create!(content: "foo")
328
+ excluded = ModelWithPgSearch.create!(content: "bar")
317
329
 
318
- results = ModelWithPgSearch.search_content('foo')
330
+ results = ModelWithPgSearch.search_content("foo")
319
331
  expect(results).to include(included)
320
332
  expect(results).not_to include(excluded)
321
333
  end
322
334
 
323
335
  it "returns the correct count" do
324
- ModelWithPgSearch.create!(content: 'foo')
325
- ModelWithPgSearch.create!(content: 'bar')
336
+ ModelWithPgSearch.create!(content: "foo")
337
+ ModelWithPgSearch.create!(content: "bar")
326
338
 
327
- results = ModelWithPgSearch.search_content('foo')
339
+ results = ModelWithPgSearch.search_content("foo")
328
340
  expect(results.count).to eq 1
329
341
  end
330
342
 
331
343
  it "returns the correct count(:all)" do
332
- ModelWithPgSearch.create!(content: 'foo')
333
- ModelWithPgSearch.create!(content: 'bar')
344
+ ModelWithPgSearch.create!(content: "foo")
345
+ ModelWithPgSearch.create!(content: "bar")
334
346
 
335
- results = ModelWithPgSearch.search_content('foo')
347
+ results = ModelWithPgSearch.search_content("foo")
336
348
  expect(results.count(:all)).to eq 1
337
349
  end
338
350
 
339
351
  it "supports #select" do
340
- record = ModelWithPgSearch.create!(content: 'foo')
341
- other_record = ModelWithPgSearch.create!(content: 'bar')
352
+ record = ModelWithPgSearch.create!(content: "foo")
353
+ ModelWithPgSearch.create!(content: "bar")
342
354
 
343
- records_with_only_id = ModelWithPgSearch.search_content('foo').select('id')
355
+ records_with_only_id = ModelWithPgSearch.search_content("foo").select("id")
344
356
  expect(records_with_only_id.length).to eq 1
345
357
 
346
358
  returned_record = records_with_only_id.first
@@ -349,36 +361,36 @@ describe "an Active Record model which includes PgSearch" do
349
361
  end
350
362
 
351
363
  it "supports #pluck" do
352
- record = ModelWithPgSearch.create!(content: 'foo')
353
- other_record = ModelWithPgSearch.create!(content: 'bar')
364
+ record = ModelWithPgSearch.create!(content: "foo")
365
+ ModelWithPgSearch.create!(content: "bar")
354
366
 
355
- ids = ModelWithPgSearch.search_content('foo').pluck('id')
367
+ ids = ModelWithPgSearch.search_content("foo").pluck("id")
356
368
  expect(ids).to eq [record.id]
357
369
  end
358
370
 
359
371
  it "supports adding where clauses using the pg_search.rank" do
360
- once = ModelWithPgSearch.create!(content: 'foo bar')
361
- twice = ModelWithPgSearch.create!(content: 'foo foo')
372
+ ModelWithPgSearch.create!(content: "foo bar")
373
+ twice = ModelWithPgSearch.create!(content: "foo foo")
362
374
 
363
- records = ModelWithPgSearch.search_content('foo')
364
- .where("#{PgSearch::Configuration.alias(ModelWithPgSearch.table_name)}.rank > 0.07")
375
+ records = ModelWithPgSearch.search_content("foo")
376
+ .where("#{PgSearch::Configuration.alias(ModelWithPgSearch.table_name)}.rank > 0.07")
365
377
 
366
378
  expect(records).to eq [twice]
367
379
  end
368
380
 
369
381
  it "returns rows where the column contains all the terms in the query in any order" do
370
- included = [ModelWithPgSearch.create!(content: 'foo bar'),
371
- ModelWithPgSearch.create!(content: 'bar foo')]
372
- excluded = ModelWithPgSearch.create!(content: 'foo')
382
+ included = [ModelWithPgSearch.create!(content: "foo bar"),
383
+ ModelWithPgSearch.create!(content: "bar foo")]
384
+ excluded = ModelWithPgSearch.create!(content: "foo")
373
385
 
374
- results = ModelWithPgSearch.search_content('foo bar')
386
+ results = ModelWithPgSearch.search_content("foo bar")
375
387
  expect(results).to match_array(included)
376
388
  expect(results).not_to include(excluded)
377
389
  end
378
390
 
379
391
  it "returns rows that match the query but not its case" do
380
392
  included = [ModelWithPgSearch.create!(content: "foo"),
381
- ModelWithPgSearch.create!(content: "FOO")]
393
+ ModelWithPgSearch.create!(content: "FOO")]
382
394
 
383
395
  results = ModelWithPgSearch.search_content("Foo")
384
396
  expect(results).to match_array(included)
@@ -397,8 +409,8 @@ describe "an Active Record model which includes PgSearch" do
397
409
  end
398
410
 
399
411
  it "returns rows that match the query but not rows that are prefixed by the query" do
400
- included = ModelWithPgSearch.create!(content: 'pre')
401
- excluded = ModelWithPgSearch.create!(content: 'prefix')
412
+ included = ModelWithPgSearch.create!(content: "pre")
413
+ excluded = ModelWithPgSearch.create!(content: "prefix")
402
414
 
403
415
  results = ModelWithPgSearch.search_content("pre")
404
416
  expect(results).to eq([included])
@@ -407,36 +419,36 @@ describe "an Active Record model which includes PgSearch" do
407
419
 
408
420
  it "returns rows that match the query exactly and not those that match the query when stemmed by the default english dictionary" do
409
421
  included = ModelWithPgSearch.create!(content: "jumped")
410
- excluded = [ModelWithPgSearch.create!(content: "jump"),
411
- ModelWithPgSearch.create!(content: "jumping")]
422
+ ModelWithPgSearch.create!(content: "jump")
423
+ ModelWithPgSearch.create!(content: "jumping")
412
424
 
413
425
  results = ModelWithPgSearch.search_content("jumped")
414
426
  expect(results).to eq([included])
415
427
  end
416
428
 
417
429
  it "returns rows that match sorted by rank" do
418
- loser = ModelWithPgSearch.create!(content: 'foo')
419
- winner = ModelWithPgSearch.create!(content: 'foo foo')
430
+ loser = ModelWithPgSearch.create!(content: "foo")
431
+ winner = ModelWithPgSearch.create!(content: "foo foo")
420
432
 
421
433
  results = ModelWithPgSearch.search_content("foo").with_pg_search_rank
422
434
  expect(results[0].pg_search_rank).to be > results[1].pg_search_rank
423
435
  expect(results).to eq([winner, loser])
424
436
  end
425
437
 
426
- it 'preserves column selection when with_pg_search_rank is chained after a select()' do
427
- loser = ModelWithPgSearch.create!(title: 'foo', content: 'bar')
438
+ it "preserves column selection when with_pg_search_rank is chained after a select()" do
439
+ ModelWithPgSearch.create!(title: "foo", content: "bar")
428
440
 
429
- results = ModelWithPgSearch.search_content('bar').select(:content).with_pg_search_rank
441
+ results = ModelWithPgSearch.search_content("bar").select(:content).with_pg_search_rank
430
442
 
431
443
  expect(results.length).to be 1
432
- expect(results.first.as_json.keys).to contain_exactly('id', 'content', 'pg_search_rank')
444
+ expect(results.first.as_json.keys).to contain_exactly("id", "content", "pg_search_rank")
433
445
  end
434
446
 
435
- it 'allows pg_search_rank along with a join' do
447
+ it "allows pg_search_rank along with a join" do
436
448
  parent_1 = ParentModel.create!(id: 98)
437
449
  parent_2 = ParentModel.create!(id: 99)
438
- loser = ModelWithPgSearch.create!(content: 'foo', parent_model: parent_2)
439
- winner = ModelWithPgSearch.create!(content: 'foo foo', parent_model: parent_1)
450
+ loser = ModelWithPgSearch.create!(content: "foo", parent_model: parent_2)
451
+ winner = ModelWithPgSearch.create!(content: "foo foo", parent_model: parent_1)
440
452
 
441
453
  results = ModelWithPgSearch.joins(:parent_model).merge(ParentModel.active).search_content("foo").with_pg_search_rank
442
454
  expect(results.map(&:id)).to eq [winner.id, loser.id]
@@ -445,8 +457,8 @@ describe "an Active Record model which includes PgSearch" do
445
457
  end
446
458
 
447
459
  it "returns results that match sorted by primary key for records that rank the same" do
448
- sorted_results = [ModelWithPgSearch.create!(content: 'foo'),
449
- ModelWithPgSearch.create!(content: 'foo')].sort_by(&:id)
460
+ sorted_results = [ModelWithPgSearch.create!(content: "foo"),
461
+ ModelWithPgSearch.create!(content: "foo")].sort_by(&:id)
450
462
 
451
463
  results = ModelWithPgSearch.search_content("foo")
452
464
  expect(results).to eq(sorted_results)
@@ -454,16 +466,16 @@ describe "an Active Record model which includes PgSearch" do
454
466
 
455
467
  it "returns results that match a query with multiple space-separated search terms" do
456
468
  included = [
457
- ModelWithPgSearch.create!(content: 'foo bar'),
458
- ModelWithPgSearch.create!(content: 'bar foo'),
459
- ModelWithPgSearch.create!(content: 'bar foo baz')
469
+ ModelWithPgSearch.create!(content: "foo bar"),
470
+ ModelWithPgSearch.create!(content: "bar foo"),
471
+ ModelWithPgSearch.create!(content: "bar foo baz")
460
472
  ]
461
473
  excluded = [
462
- ModelWithPgSearch.create!(content: 'foo'),
463
- ModelWithPgSearch.create!(content: 'foo baz')
474
+ ModelWithPgSearch.create!(content: "foo"),
475
+ ModelWithPgSearch.create!(content: "foo baz")
464
476
  ]
465
477
 
466
- results = ModelWithPgSearch.search_content('foo bar')
478
+ results = ModelWithPgSearch.search_content("foo bar")
467
479
  expect(results).to match_array(included)
468
480
  expect(results).not_to include(excluded)
469
481
  end
@@ -477,7 +489,7 @@ describe "an Active Record model which includes PgSearch" do
477
489
 
478
490
  it "accepts non-string queries and calls #to_s on them" do
479
491
  foo = ModelWithPgSearch.create!(content: "foo")
480
- not_a_string = instance_double("Object", to_s: "foo")
492
+ not_a_string = instance_double(Object, to_s: "foo")
481
493
  expect(ModelWithPgSearch.search_content(not_a_string)).to eq([foo])
482
494
  end
483
495
 
@@ -493,7 +505,7 @@ describe "an Active Record model which includes PgSearch" do
493
505
  # WARNING: searching timestamps is not something PostgreSQL
494
506
  # full-text search is good at. Use at your own risk.
495
507
  pg_search_scope :search_timestamps,
496
- against: %i[created_at updated_at]
508
+ against: %i[created_at updated_at]
497
509
  end
498
510
  end
499
511
 
@@ -514,15 +526,15 @@ describe "an Active Record model which includes PgSearch" do
514
526
 
515
527
  it "returns rows whose columns contain all of the terms in the query across columns" do
516
528
  included = [
517
- ModelWithPgSearch.create!(title: 'foo', content: 'bar'),
518
- ModelWithPgSearch.create!(title: 'bar', content: 'foo')
529
+ ModelWithPgSearch.create!(title: "foo", content: "bar"),
530
+ ModelWithPgSearch.create!(title: "bar", content: "foo")
519
531
  ]
520
532
  excluded = [
521
- ModelWithPgSearch.create!(title: 'foo', content: 'foo'),
522
- ModelWithPgSearch.create!(title: 'bar', content: 'bar')
533
+ ModelWithPgSearch.create!(title: "foo", content: "foo"),
534
+ ModelWithPgSearch.create!(title: "bar", content: "bar")
523
535
  ]
524
536
 
525
- results = ModelWithPgSearch.search_title_and_content('foo bar')
537
+ results = ModelWithPgSearch.search_title_and_content("foo bar")
526
538
 
527
539
  expect(results).to match_array(included)
528
540
  excluded.each do |result|
@@ -531,17 +543,17 @@ describe "an Active Record model which includes PgSearch" do
531
543
  end
532
544
 
533
545
  it "returns rows where at one column contains all of the terms in the query and another does not" do
534
- in_title = ModelWithPgSearch.create!(title: 'foo', content: 'bar')
535
- in_content = ModelWithPgSearch.create!(title: 'bar', content: 'foo')
546
+ in_title = ModelWithPgSearch.create!(title: "foo", content: "bar")
547
+ in_content = ModelWithPgSearch.create!(title: "bar", content: "foo")
536
548
 
537
- results = ModelWithPgSearch.search_title_and_content('foo')
538
- expect(results).to match_array([in_title, in_content])
549
+ results = ModelWithPgSearch.search_title_and_content("foo")
550
+ expect(results).to contain_exactly(in_title, in_content)
539
551
  end
540
552
 
541
553
  # Searching with a NULL column will prevent any matches unless we coalesce it.
542
554
  it "returns rows where at one column contains all of the terms in the query and another is NULL" do
543
- included = ModelWithPgSearch.create!(title: 'foo', content: nil)
544
- results = ModelWithPgSearch.search_title_and_content('foo')
555
+ included = ModelWithPgSearch.create!(title: "foo", content: nil)
556
+ results = ModelWithPgSearch.search_title_and_content("foo")
545
557
  expect(results).to eq([included])
546
558
  end
547
559
  end
@@ -552,21 +564,21 @@ describe "an Active Record model which includes PgSearch" do
552
564
  end
553
565
 
554
566
  it "returns rows where one searchable column and the query share enough trigrams" do
555
- included = ModelWithPgSearch.create!(title: 'abcdefghijkl', content: nil)
556
- results = ModelWithPgSearch.with_trigrams('cdefhijkl')
567
+ included = ModelWithPgSearch.create!(title: "abcdefghijkl", content: nil)
568
+ results = ModelWithPgSearch.with_trigrams("cdefhijkl")
557
569
  expect(results).to eq([included])
558
570
  end
559
571
 
560
572
  it "returns rows where multiple searchable columns and the query share enough trigrams" do
561
- included = ModelWithPgSearch.create!(title: 'abcdef', content: 'ghijkl')
562
- results = ModelWithPgSearch.with_trigrams('cdefhijkl')
573
+ included = ModelWithPgSearch.create!(title: "abcdef", content: "ghijkl")
574
+ results = ModelWithPgSearch.with_trigrams("cdefhijkl")
563
575
  expect(results).to eq([included])
564
576
  end
565
577
 
566
578
  context "when a threshold is specified" do
567
579
  before do
568
- ModelWithPgSearch.pg_search_scope :with_strict_trigrams, against: %i[title content], using: { trigram: { threshold: 0.5 } }
569
- ModelWithPgSearch.pg_search_scope :with_permissive_trigrams, against: %i[title content], using: { trigram: { threshold: 0.1 } }
580
+ ModelWithPgSearch.pg_search_scope :with_strict_trigrams, against: %i[title content], using: {trigram: {threshold: 0.5}}
581
+ ModelWithPgSearch.pg_search_scope :with_permissive_trigrams, against: %i[title content], using: {trigram: {threshold: 0.1}}
570
582
  end
571
583
 
572
584
  it "uses the threshold in the trigram expression" do
@@ -591,16 +603,16 @@ describe "an Active Record model which includes PgSearch" do
591
603
  context "when using tsearch" do
592
604
  before do
593
605
  ModelWithPgSearch.pg_search_scope :search_title_with_prefixes,
594
- against: :title,
595
- using: {
596
- tsearch: { prefix: true }
597
- }
606
+ against: :title,
607
+ using: {
608
+ tsearch: {prefix: true}
609
+ }
598
610
  end
599
611
 
600
612
  context "with prefix: true" do
601
613
  it "returns rows that match the query and that are prefixed by the query" do
602
- included = ModelWithPgSearch.create!(title: 'prefix')
603
- excluded = ModelWithPgSearch.create!(title: 'postfix')
614
+ included = ModelWithPgSearch.create!(title: "prefix")
615
+ excluded = ModelWithPgSearch.create!(title: "postfix")
604
616
 
605
617
  results = ModelWithPgSearch.search_title_with_prefixes("pre")
606
618
  expect(results).to eq([included])
@@ -608,8 +620,8 @@ describe "an Active Record model which includes PgSearch" do
608
620
  end
609
621
 
610
622
  it "returns rows that match the query when the query has a hyphen" do
611
- included = ModelWithPgSearch.create!(title: 'foo-bar')
612
- excluded = ModelWithPgSearch.create!(title: 'foo bar')
623
+ included = ModelWithPgSearch.create!(title: "foo-bar")
624
+ excluded = ModelWithPgSearch.create!(title: "foo bar")
613
625
 
614
626
  results = ModelWithPgSearch.search_title_with_prefixes("foo-bar")
615
627
  expect(results).to include(included)
@@ -620,16 +632,16 @@ describe "an Active Record model which includes PgSearch" do
620
632
  context "with the english dictionary" do
621
633
  before do
622
634
  ModelWithPgSearch.pg_search_scope :search_content_with_english,
623
- against: :content,
624
- using: {
625
- tsearch: { dictionary: :english }
626
- }
635
+ against: :content,
636
+ using: {
637
+ tsearch: {dictionary: :english}
638
+ }
627
639
  end
628
640
 
629
641
  it "returns rows that match the query when stemmed by the english dictionary" do
630
642
  included = [ModelWithPgSearch.create!(content: "jump"),
631
- ModelWithPgSearch.create!(content: "jumped"),
632
- ModelWithPgSearch.create!(content: "jumping")]
643
+ ModelWithPgSearch.create!(content: "jumped"),
644
+ ModelWithPgSearch.create!(content: "jumping")]
633
645
 
634
646
  results = ModelWithPgSearch.search_content_with_english("jump")
635
647
  expect(results).to match_array(included)
@@ -639,14 +651,14 @@ describe "an Active Record model which includes PgSearch" do
639
651
  describe "highlighting" do
640
652
  before do
641
653
  ["Strip Down", "Down", "Down and Out", "Won't Let You Down"].each do |name|
642
- ModelWithPgSearch.create! title: 'Just a title', content: name
654
+ ModelWithPgSearch.create! title: "Just a title", content: name
643
655
  end
644
656
  end
645
657
 
646
658
  context "with highlight turned on" do
647
659
  before do
648
660
  ModelWithPgSearch.pg_search_scope :search_content,
649
- against: :content
661
+ against: :content
650
662
  end
651
663
 
652
664
  it "adds a #pg_search_highlight method to each returned model record" do
@@ -661,31 +673,31 @@ describe "an Active Record model which includes PgSearch" do
661
673
  expect(result.pg_search_highlight).to eq("Won't <b>Let</b> You Down")
662
674
  end
663
675
 
664
- it 'preserves column selection when with_pg_search_highlight is chained after a select()' do
676
+ it "preserves column selection when with_pg_search_highlight is chained after a select()" do
665
677
  result = ModelWithPgSearch.search_content("Let").select(:content).with_pg_search_highlight.first
666
678
 
667
- expect(result.as_json.keys).to contain_exactly('id', 'content', 'pg_search_highlight')
679
+ expect(result.as_json.keys).to contain_exactly("id", "content", "pg_search_highlight")
668
680
  end
669
681
  end
670
682
 
671
683
  context "with custom highlighting options" do
672
684
  before do
673
- ModelWithPgSearch.create! content: "#{'text ' * 2}Let #{'text ' * 2}Let #{'text ' * 2}"
685
+ ModelWithPgSearch.create! content: "#{"text " * 2}Let #{"text " * 2}Let #{"text " * 2}"
674
686
 
675
687
  ModelWithPgSearch.pg_search_scope :search_content,
676
- against: :content,
677
- using: {
678
- tsearch: {
679
- highlight: {
680
- StartSel: '<mark class="highlight">',
681
- StopSel: '</mark>',
682
- FragmentDelimiter: '<delim class="my_delim">',
683
- MaxFragments: 2,
684
- MaxWords: 2,
685
- MinWords: 1
686
- }
687
- }
688
- }
688
+ against: :content,
689
+ using: {
690
+ tsearch: {
691
+ highlight: {
692
+ StartSel: '<mark class="highlight">',
693
+ StopSel: "</mark>",
694
+ FragmentDelimiter: '<delim class="my_delim">',
695
+ MaxFragments: 2,
696
+ MaxWords: 2,
697
+ MinWords: 1
698
+ }
699
+ }
700
+ }
689
701
  end
690
702
 
691
703
  it "applies the options to the excerpts" do
@@ -714,10 +726,10 @@ describe "an Active Record model which includes PgSearch" do
714
726
  context "with a normalization specified" do
715
727
  before do
716
728
  ModelWithPgSearch.pg_search_scope :search_content_with_normalization,
717
- against: :content,
718
- using: {
719
- tsearch: { normalization: 2 }
720
- }
729
+ against: :content,
730
+ using: {
731
+ tsearch: {normalization: 2}
732
+ }
721
733
  end
722
734
 
723
735
  it "ranks the results for documents with less text higher" do
@@ -731,8 +743,8 @@ describe "an Active Record model which includes PgSearch" do
731
743
  context "with no normalization" do
732
744
  before do
733
745
  ModelWithPgSearch.pg_search_scope :search_content_without_normalization,
734
- against: :content,
735
- using: :tsearch
746
+ against: :content,
747
+ using: :tsearch
736
748
  end
737
749
 
738
750
  it "ranks the results equally" do
@@ -747,14 +759,14 @@ describe "an Active Record model which includes PgSearch" do
747
759
  context "when against columns ranked with arrays" do
748
760
  before do
749
761
  ModelWithPgSearch.pg_search_scope :search_weighted_by_array_of_arrays,
750
- against: [[:content, 'B'], [:title, 'A']]
762
+ against: [[:content, "B"], [:title, "A"]]
751
763
  end
752
764
 
753
765
  it "returns results sorted by weighted rank" do
754
- loser = ModelWithPgSearch.create!(title: 'bar', content: 'foo')
755
- winner = ModelWithPgSearch.create!(title: 'foo', content: 'bar')
766
+ loser = ModelWithPgSearch.create!(title: "bar", content: "foo")
767
+ winner = ModelWithPgSearch.create!(title: "foo", content: "bar")
756
768
 
757
- results = ModelWithPgSearch.search_weighted_by_array_of_arrays('foo').with_pg_search_rank
769
+ results = ModelWithPgSearch.search_weighted_by_array_of_arrays("foo").with_pg_search_rank
758
770
  expect(results[0].pg_search_rank).to be > results[1].pg_search_rank
759
771
  expect(results).to eq([winner, loser])
760
772
  end
@@ -763,14 +775,14 @@ describe "an Active Record model which includes PgSearch" do
763
775
  context "when against columns ranked with a hash" do
764
776
  before do
765
777
  ModelWithPgSearch.pg_search_scope :search_weighted_by_hash,
766
- against: { content: 'B', title: 'A' }
778
+ against: {content: "B", title: "A"}
767
779
  end
768
780
 
769
781
  it "returns results sorted by weighted rank" do
770
- loser = ModelWithPgSearch.create!(title: 'bar', content: 'foo')
771
- winner = ModelWithPgSearch.create!(title: 'foo', content: 'bar')
782
+ loser = ModelWithPgSearch.create!(title: "bar", content: "foo")
783
+ winner = ModelWithPgSearch.create!(title: "foo", content: "bar")
772
784
 
773
- results = ModelWithPgSearch.search_weighted_by_hash('foo').with_pg_search_rank
785
+ results = ModelWithPgSearch.search_weighted_by_hash("foo").with_pg_search_rank
774
786
  expect(results[0].pg_search_rank).to be > results[1].pg_search_rank
775
787
  expect(results).to eq([winner, loser])
776
788
  end
@@ -779,14 +791,14 @@ describe "an Active Record model which includes PgSearch" do
779
791
  context "when against columns of which only some are ranked" do
780
792
  before do
781
793
  ModelWithPgSearch.pg_search_scope :search_weighted,
782
- against: [:content, [:title, 'A']]
794
+ against: [:content, [:title, "A"]]
783
795
  end
784
796
 
785
797
  it "returns results sorted by weighted rank using an implied low rank for unranked columns" do
786
- loser = ModelWithPgSearch.create!(title: 'bar', content: 'foo')
787
- winner = ModelWithPgSearch.create!(title: 'foo', content: 'bar')
798
+ loser = ModelWithPgSearch.create!(title: "bar", content: "foo")
799
+ winner = ModelWithPgSearch.create!(title: "foo", content: "bar")
788
800
 
789
- results = ModelWithPgSearch.search_weighted('foo').with_pg_search_rank
801
+ results = ModelWithPgSearch.search_weighted("foo").with_pg_search_rank
790
802
  expect(results[0].pg_search_rank).to be > results[1].pg_search_rank
791
803
  expect(results).to eq([winner, loser])
792
804
  end
@@ -795,17 +807,17 @@ describe "an Active Record model which includes PgSearch" do
795
807
  context "when searching any_word option" do
796
808
  before do
797
809
  ModelWithPgSearch.pg_search_scope :search_title_with_any_word,
798
- against: :title,
799
- using: {
800
- tsearch: { any_word: true }
801
- }
810
+ against: :title,
811
+ using: {
812
+ tsearch: {any_word: true}
813
+ }
802
814
 
803
815
  ModelWithPgSearch.pg_search_scope :search_title_with_all_words,
804
- against: :title
816
+ against: :title
805
817
  end
806
818
 
807
819
  it "returns all results containing any word in their title" do
808
- numbers = %w[one two three four].map { |number| ModelWithPgSearch.create!(title: number) }
820
+ %w[one two three four].map { |number| ModelWithPgSearch.create!(title: number) }
809
821
 
810
822
  results = ModelWithPgSearch.search_title_with_any_word("one two three four")
811
823
 
@@ -820,10 +832,10 @@ describe "an Active Record model which includes PgSearch" do
820
832
  context "with :negation" do
821
833
  before do
822
834
  ModelWithPgSearch.pg_search_scope :search_with_negation,
823
- against: :title,
824
- using: {
825
- tsearch: { negation: true }
826
- }
835
+ against: :title,
836
+ using: {
837
+ tsearch: {negation: true}
838
+ }
827
839
  end
828
840
 
829
841
  it "doesn't return results that contain terms prepended with '!'" do
@@ -847,10 +859,10 @@ describe "an Active Record model which includes PgSearch" do
847
859
  context "without :negation" do
848
860
  before do
849
861
  ModelWithPgSearch.pg_search_scope :search_without_negation,
850
- against: :title,
851
- using: {
852
- tsearch: {}
853
- }
862
+ against: :title,
863
+ using: {
864
+ tsearch: {}
865
+ }
854
866
  end
855
867
 
856
868
  it "return results that contain terms prepended with '!'" do
@@ -873,38 +885,37 @@ describe "an Active Record model which includes PgSearch" do
873
885
  context "when using dmetaphone" do
874
886
  before do
875
887
  ModelWithPgSearch.pg_search_scope :with_dmetaphones,
876
- against: %i[title content],
877
- using: :dmetaphone
888
+ against: %i[title content],
889
+ using: :dmetaphone
878
890
  end
879
891
 
880
892
  it "returns rows where one searchable column and the query share enough dmetaphones" do
881
- included = ModelWithPgSearch.create!(title: 'Geoff', content: nil)
882
- excluded = ModelWithPgSearch.create!(title: 'Bob', content: nil)
883
- results = ModelWithPgSearch.with_dmetaphones('Jeff')
893
+ included = ModelWithPgSearch.create!(title: "Geoff", content: nil)
894
+ ModelWithPgSearch.create!(title: "Bob", content: nil)
895
+ results = ModelWithPgSearch.with_dmetaphones("Jeff")
884
896
  expect(results).to eq([included])
885
897
  end
886
898
 
887
899
  it "returns rows where multiple searchable columns and the query share enough dmetaphones" do
888
- included = ModelWithPgSearch.create!(title: 'Geoff', content: 'George')
889
- excluded = ModelWithPgSearch.create!(title: 'Bob', content: 'Jones')
890
- results = ModelWithPgSearch.with_dmetaphones('Jeff Jorge')
900
+ included = ModelWithPgSearch.create!(title: "Geoff", content: "George")
901
+ ModelWithPgSearch.create!(title: "Bob", content: "Jones")
902
+ results = ModelWithPgSearch.with_dmetaphones("Jeff Jorge")
891
903
  expect(results).to eq([included])
892
904
  end
893
905
 
894
906
  it "returns rows that match dmetaphones that are English stopwords" do
895
- included = ModelWithPgSearch.create!(title: 'White', content: nil)
896
- excluded = ModelWithPgSearch.create!(title: 'Black', content: nil)
897
- results = ModelWithPgSearch.with_dmetaphones('Wight')
907
+ included = ModelWithPgSearch.create!(title: "White", content: nil)
908
+ ModelWithPgSearch.create!(title: "Black", content: nil)
909
+ results = ModelWithPgSearch.with_dmetaphones("Wight")
898
910
  expect(results).to eq([included])
899
911
  end
900
912
 
901
913
  it "can handle terms that do not have a dmetaphone equivalent" do
902
- term_with_blank_metaphone = "w"
903
-
904
- included = ModelWithPgSearch.create!(title: 'White', content: nil)
905
- excluded = ModelWithPgSearch.create!(title: 'Black', content: nil)
914
+ included = ModelWithPgSearch.create!(title: "White", content: nil)
915
+ ModelWithPgSearch.create!(title: "Black", content: nil)
906
916
 
907
- results = ModelWithPgSearch.with_dmetaphones('Wight W')
917
+ # "W" does not have a dmetaphone equivalent
918
+ results = ModelWithPgSearch.with_dmetaphones("Wight W")
908
919
  expect(results).to eq([included])
909
920
  end
910
921
  end
@@ -912,35 +923,35 @@ describe "an Active Record model which includes PgSearch" do
912
923
  context "when using multiple features" do
913
924
  before do
914
925
  ModelWithPgSearch.pg_search_scope :with_tsearch,
915
- against: :title,
916
- using: [
917
- [:tsearch, { dictionary: 'english' }]
918
- ]
926
+ against: :title,
927
+ using: [
928
+ [:tsearch, {dictionary: "english"}]
929
+ ]
919
930
 
920
931
  ModelWithPgSearch.pg_search_scope :with_trigram,
921
- against: :title,
922
- using: :trigram
932
+ against: :title,
933
+ using: :trigram
923
934
 
924
935
  ModelWithPgSearch.pg_search_scope :with_trigram_and_ignoring_accents,
925
- against: :title,
926
- ignoring: :accents,
927
- using: :trigram
936
+ against: :title,
937
+ ignoring: :accents,
938
+ using: :trigram
928
939
 
929
940
  ModelWithPgSearch.pg_search_scope :with_tsearch_and_trigram,
930
- against: :title,
931
- using: [
932
- [:tsearch, { dictionary: 'english' }],
933
- :trigram
934
- ]
941
+ against: :title,
942
+ using: [
943
+ [:tsearch, {dictionary: "english"}],
944
+ :trigram
945
+ ]
935
946
 
936
947
  ModelWithPgSearch.pg_search_scope :complex_search,
937
- against: %i[content title],
938
- ignoring: :accents,
939
- using: {
940
- tsearch: { dictionary: 'english' },
941
- dmetaphone: {},
942
- trigram: {}
943
- }
948
+ against: %i[content title],
949
+ ignoring: :accents,
950
+ using: {
951
+ tsearch: {dictionary: "english"},
952
+ dmetaphone: {},
953
+ trigram: {}
954
+ }
944
955
  end
945
956
 
946
957
  it "returns rows that match using any of the features" do
@@ -982,24 +993,24 @@ describe "an Active Record model which includes PgSearch" do
982
993
  end
983
994
 
984
995
  context "with feature-specific configuration" do
985
- let(:tsearch_config) { { dictionary: 'english' } }
986
- let(:trigram_config) { { foo: 'bar' } }
996
+ let(:tsearch_config) { {dictionary: "english"} }
997
+ let(:trigram_config) { {foo: "bar"} }
987
998
 
988
999
  before do
989
1000
  ModelWithPgSearch.pg_search_scope :with_tsearch_and_trigram_using_hash,
990
- against: :title,
991
- using: { tsearch: tsearch_config, trigram: trigram_config }
1001
+ against: :title,
1002
+ using: {tsearch: tsearch_config, trigram: trigram_config}
992
1003
  end
993
1004
 
994
1005
  it "passes the custom configuration down to the specified feature" do
995
1006
  tsearch_feature = instance_double(
996
- "PgSearch::Features::TSearch",
1007
+ PgSearch::Features::TSearch,
997
1008
  conditions: Arel::Nodes::Grouping.new(Arel.sql("1 = 1")),
998
1009
  rank: Arel::Nodes::Grouping.new(Arel.sql("1.0"))
999
1010
  )
1000
1011
 
1001
1012
  trigram_feature = instance_double(
1002
- "PgSearch::Features::Trigram",
1013
+ PgSearch::Features::Trigram,
1003
1014
  conditions: Arel::Nodes::Grouping.new(Arel.sql("1 = 1")),
1004
1015
  rank: Arel::Nodes::Grouping.new(Arel.sql("1.0"))
1005
1016
  )
@@ -1029,8 +1040,8 @@ describe "an Active Record model which includes PgSearch" do
1029
1040
 
1030
1041
  with_model :Post do
1031
1042
  table do |t|
1032
- t.text 'content'
1033
- t.tsvector 'content_tsvector'
1043
+ t.text "content"
1044
+ t.tsvector "content_tsvector"
1034
1045
  end
1035
1046
 
1036
1047
  model do
@@ -1039,8 +1050,8 @@ describe "an Active Record model which includes PgSearch" do
1039
1050
  end
1040
1051
  end
1041
1052
 
1042
- let!(:expected) { Post.create!(content: 'phooey') }
1043
- let!(:unexpected) { Post.create!(content: 'longcat is looooooooong') }
1053
+ let!(:expected) { Post.create!(content: "phooey") }
1054
+ let!(:unexpected) { Post.create!(content: "longcat is looooooooong") }
1044
1055
 
1045
1056
  before do
1046
1057
  ActiveRecord::Base.connection.execute <<~SQL.squish
@@ -1048,17 +1059,17 @@ describe "an Active Record model which includes PgSearch" do
1048
1059
  SET content_tsvector = to_tsvector('english'::regconfig, #{Post.quoted_table_name}."content")
1049
1060
  SQL
1050
1061
 
1051
- expected.comments.create(body: 'commentone')
1052
- unexpected.comments.create(body: 'commentwo')
1062
+ expected.comments.create!(body: "commentone")
1063
+ unexpected.comments.create!(body: "commentwo")
1053
1064
 
1054
1065
  Post.pg_search_scope :search_by_content_with_tsvector,
1055
- associated_against: { comments: [:body] },
1056
- using: {
1057
- tsearch: {
1058
- tsvector_column: 'content_tsvector',
1059
- dictionary: 'english'
1060
- }
1061
- }
1066
+ associated_against: {comments: [:body]},
1067
+ using: {
1068
+ tsearch: {
1069
+ tsvector_column: "content_tsvector",
1070
+ dictionary: "english"
1071
+ }
1072
+ }
1062
1073
  end
1063
1074
 
1064
1075
  it "finds by the tsvector column" do
@@ -1069,29 +1080,29 @@ describe "an Active Record model which includes PgSearch" do
1069
1080
  expect(Post.search_by_content_with_tsvector("commentone").map(&:id)).to eq([expected.id])
1070
1081
  end
1071
1082
 
1072
- it 'finds by a combination of the two' do
1083
+ it "finds by a combination of the two" do
1073
1084
  expect(Post.search_by_content_with_tsvector("phooey commentone").map(&:id)).to eq([expected.id])
1074
1085
  end
1075
1086
  end
1076
1087
 
1077
- context 'when using multiple tsvector columns' do
1088
+ context "when using multiple tsvector columns" do
1078
1089
  with_model :ModelWithTsvector do
1079
1090
  model do
1080
1091
  include PgSearch::Model
1081
1092
 
1082
1093
  pg_search_scope :search_by_multiple_tsvector_columns,
1083
- against: ['content', 'message'],
1084
- using: {
1085
- tsearch: {
1086
- tsvector_column: ['content_tsvector', 'message_tsvector'],
1087
- dictionary: 'english'
1088
- }
1089
- }
1094
+ against: ["content", "message"],
1095
+ using: {
1096
+ tsearch: {
1097
+ tsvector_column: ["content_tsvector", "message_tsvector"],
1098
+ dictionary: "english"
1099
+ }
1100
+ }
1090
1101
  end
1091
1102
  end
1092
1103
 
1093
- it 'concats tsvector columns' do
1094
- expected = "#{ModelWithTsvector.quoted_table_name}.\"content_tsvector\" || "\
1104
+ it "concats tsvector columns" do
1105
+ expected = "#{ModelWithTsvector.quoted_table_name}.\"content_tsvector\" || " \
1095
1106
  "#{ModelWithTsvector.quoted_table_name}.\"message_tsvector\""
1096
1107
 
1097
1108
  expect(ModelWithTsvector.search_by_multiple_tsvector_columns("something").to_sql).to include(expected)
@@ -1101,17 +1112,17 @@ describe "an Active Record model which includes PgSearch" do
1101
1112
  context "when using a tsvector column with" do
1102
1113
  with_model :ModelWithTsvector do
1103
1114
  table do |t|
1104
- t.text 'content'
1105
- t.tsvector 'content_tsvector'
1115
+ t.text "content"
1116
+ t.tsvector "content_tsvector"
1106
1117
  end
1107
1118
 
1108
1119
  model { include PgSearch::Model }
1109
1120
  end
1110
1121
 
1111
- let!(:expected) { ModelWithTsvector.create!(content: 'tiling is grouty') }
1122
+ let!(:expected) { ModelWithTsvector.create!(content: "tiling is grouty") }
1112
1123
 
1113
1124
  before do
1114
- ModelWithTsvector.create!(content: 'longcat is looooooooong')
1125
+ ModelWithTsvector.create!(content: "longcat is looooooooong")
1115
1126
 
1116
1127
  ActiveRecord::Base.connection.execute <<~SQL.squish
1117
1128
  UPDATE #{ModelWithTsvector.quoted_table_name}
@@ -1119,13 +1130,13 @@ describe "an Active Record model which includes PgSearch" do
1119
1130
  SQL
1120
1131
 
1121
1132
  ModelWithTsvector.pg_search_scope :search_by_content_with_tsvector,
1122
- against: :content,
1123
- using: {
1124
- tsearch: {
1125
- tsvector_column: 'content_tsvector',
1126
- dictionary: 'english'
1127
- }
1128
- }
1133
+ against: :content,
1134
+ using: {
1135
+ tsearch: {
1136
+ tsvector_column: "content_tsvector",
1137
+ dictionary: "english"
1138
+ }
1139
+ }
1129
1140
  end
1130
1141
 
1131
1142
  it "does not use to_tsvector in the query" do
@@ -1159,8 +1170,8 @@ describe "an Active Record model which includes PgSearch" do
1159
1170
  context "when ignoring accents" do
1160
1171
  before do
1161
1172
  ModelWithPgSearch.pg_search_scope :search_title_without_accents,
1162
- against: :title,
1163
- ignoring: :accents
1173
+ against: :title,
1174
+ ignoring: :accents
1164
1175
  end
1165
1176
 
1166
1177
  it "returns rows that match the query but not its accents" do
@@ -1174,11 +1185,16 @@ describe "an Active Record model which includes PgSearch" do
1174
1185
  end
1175
1186
 
1176
1187
  context "when the query includes accents" do
1177
- it "does not create an erroneous tsquery expression" do
1178
- included = ModelWithPgSearch.create!(title: "Weird L‘Content")
1188
+ let(:term) { "L#{%w[‘ ʻ ʼ].sample}Content" }
1189
+ let(:included) { ModelWithPgSearch.create!(title: "Weird #{term}") }
1190
+ let(:results) { ModelWithPgSearch.search_title_without_accents(term) }
1179
1191
 
1180
- results = ModelWithPgSearch.search_title_without_accents("L‘Content")
1181
- expect(results).to eq([included])
1192
+ before do
1193
+ ModelWithPgSearch.create!(title: "FooBar")
1194
+ end
1195
+
1196
+ it "does not create an erroneous tsquery expression" do
1197
+ expect(results).to contain_exactly(included)
1182
1198
  end
1183
1199
  end
1184
1200
  end
@@ -1186,25 +1202,25 @@ describe "an Active Record model which includes PgSearch" do
1186
1202
  context "when passed a :ranked_by expression" do
1187
1203
  before do
1188
1204
  ModelWithPgSearch.pg_search_scope :search_content_with_default_rank,
1189
- against: :content
1205
+ against: :content
1190
1206
 
1191
1207
  ModelWithPgSearch.pg_search_scope :search_content_with_importance_as_rank,
1192
- against: :content,
1193
- ranked_by: "importance"
1208
+ against: :content,
1209
+ ranked_by: "importance"
1194
1210
 
1195
1211
  ModelWithPgSearch.pg_search_scope :search_content_with_importance_as_rank_multiplier,
1196
- against: :content,
1197
- ranked_by: ":tsearch * importance"
1212
+ against: :content,
1213
+ ranked_by: ":tsearch * importance"
1198
1214
  end
1199
1215
 
1200
1216
  it "returns records with a rank attribute equal to the :ranked_by expression" do
1201
- ModelWithPgSearch.create!(content: 'foo', importance: 10)
1217
+ ModelWithPgSearch.create!(content: "foo", importance: 10)
1202
1218
  results = ModelWithPgSearch.search_content_with_importance_as_rank("foo").with_pg_search_rank
1203
1219
  expect(results.first.pg_search_rank).to eq(10)
1204
1220
  end
1205
1221
 
1206
1222
  it "substitutes :tsearch with the tsearch rank expression in the :ranked_by expression" do
1207
- ModelWithPgSearch.create!(content: 'foo', importance: 10)
1223
+ ModelWithPgSearch.create!(content: "foo", importance: 10)
1208
1224
 
1209
1225
  tsearch_result =
1210
1226
  ModelWithPgSearch.search_content_with_default_rank("foo").with_pg_search_rank.first
@@ -1213,8 +1229,8 @@ describe "an Active Record model which includes PgSearch" do
1213
1229
 
1214
1230
  multiplied_result =
1215
1231
  ModelWithPgSearch.search_content_with_importance_as_rank_multiplier("foo")
1216
- .with_pg_search_rank
1217
- .first
1232
+ .with_pg_search_rank
1233
+ .first
1218
1234
 
1219
1235
  multiplied_rank = multiplied_result.pg_search_rank
1220
1236
 
@@ -1223,9 +1239,9 @@ describe "an Active Record model which includes PgSearch" do
1223
1239
 
1224
1240
  it "returns results in descending order of the value of the rank expression" do
1225
1241
  records = [
1226
- ModelWithPgSearch.create!(content: 'foo', importance: 1),
1227
- ModelWithPgSearch.create!(content: 'foo', importance: 3),
1228
- ModelWithPgSearch.create!(content: 'foo', importance: 2)
1242
+ ModelWithPgSearch.create!(content: "foo", importance: 1),
1243
+ ModelWithPgSearch.create!(content: "foo", importance: 3),
1244
+ ModelWithPgSearch.create!(content: "foo", importance: 2)
1229
1245
  ]
1230
1246
 
1231
1247
  results = ModelWithPgSearch.search_content_with_importance_as_rank("foo")
@@ -1238,32 +1254,32 @@ describe "an Active Record model which includes PgSearch" do
1238
1254
 
1239
1255
  before do
1240
1256
  ModelWithPgSearch.pg_search_scope scope_name,
1241
- against: :content,
1242
- ranked_by: ":#{feature}"
1257
+ against: :content,
1258
+ ranked_by: ":#{feature}"
1243
1259
 
1244
- ModelWithPgSearch.create!(content: 'foo')
1260
+ ModelWithPgSearch.create!(content: "foo")
1245
1261
  end
1246
1262
 
1247
1263
  context "when .with_pg_search_rank is chained after" do
1248
1264
  specify "its results respond to #pg_search_rank" do
1249
- result = ModelWithPgSearch.send(scope_name, 'foo').with_pg_search_rank.first
1265
+ result = ModelWithPgSearch.send(scope_name, "foo").with_pg_search_rank.first
1250
1266
  expect(result).to respond_to(:pg_search_rank)
1251
1267
  end
1252
1268
 
1253
1269
  it "returns the rank when #pg_search_rank is called on a result" do
1254
- results = ModelWithPgSearch.send(scope_name, 'foo').with_pg_search_rank
1270
+ results = ModelWithPgSearch.send(scope_name, "foo").with_pg_search_rank
1255
1271
  expect(results.first.pg_search_rank).to be_a Float
1256
1272
  end
1257
1273
  end
1258
1274
 
1259
1275
  context "when .with_pg_search_rank is not chained after" do
1260
1276
  specify "its results do not respond to #pg_search_rank" do
1261
- result = ModelWithPgSearch.send(scope_name, 'foo').first
1277
+ result = ModelWithPgSearch.send(scope_name, "foo").first
1262
1278
  expect(result).not_to respond_to(:pg_search_rank)
1263
1279
  end
1264
1280
 
1265
1281
  it "raises PgSearch::PgSearchRankNotSelected when #pg_search_rank is called on a result" do
1266
- result = ModelWithPgSearch.send(scope_name, 'foo').first
1282
+ result = ModelWithPgSearch.send(scope_name, "foo").first
1267
1283
  expect {
1268
1284
  result.pg_search_rank
1269
1285
  }.to raise_exception(PgSearch::PgSearchRankNotSelected)
@@ -1275,14 +1291,14 @@ describe "an Active Record model which includes PgSearch" do
1275
1291
  context "when using the tsearch ranking algorithm" do
1276
1292
  it "sorts results by the tsearch rank" do
1277
1293
  ModelWithPgSearch.pg_search_scope :search_content_ranked_by_tsearch,
1278
- using: :tsearch,
1279
- against: :content,
1280
- ranked_by: ":tsearch"
1294
+ using: :tsearch,
1295
+ against: :content,
1296
+ ranked_by: ":tsearch"
1281
1297
 
1282
- once = ModelWithPgSearch.create!(content: 'foo bar')
1283
- twice = ModelWithPgSearch.create!(content: 'foo foo')
1298
+ once = ModelWithPgSearch.create!(content: "foo bar")
1299
+ twice = ModelWithPgSearch.create!(content: "foo foo")
1284
1300
 
1285
- results = ModelWithPgSearch.search_content_ranked_by_tsearch('foo')
1301
+ results = ModelWithPgSearch.search_content_ranked_by_tsearch("foo")
1286
1302
  expect(results.find_index(twice)).to be < results.find_index(once)
1287
1303
  end
1288
1304
  end
@@ -1290,14 +1306,14 @@ describe "an Active Record model which includes PgSearch" do
1290
1306
  context "when using the trigram ranking algorithm" do
1291
1307
  it "sorts results by the trigram rank" do
1292
1308
  ModelWithPgSearch.pg_search_scope :search_content_ranked_by_trigram,
1293
- using: :trigram,
1294
- against: :content,
1295
- ranked_by: ":trigram"
1309
+ using: :trigram,
1310
+ against: :content,
1311
+ ranked_by: ":trigram"
1296
1312
 
1297
- close = ModelWithPgSearch.create!(content: 'abcdef')
1298
- exact = ModelWithPgSearch.create!(content: 'abc')
1313
+ close = ModelWithPgSearch.create!(content: "abcdef")
1314
+ exact = ModelWithPgSearch.create!(content: "abc")
1299
1315
 
1300
- results = ModelWithPgSearch.search_content_ranked_by_trigram('abc')
1316
+ results = ModelWithPgSearch.search_content_ranked_by_trigram("abc")
1301
1317
  expect(results.find_index(exact)).to be < results.find_index(close)
1302
1318
  end
1303
1319
  end
@@ -1305,14 +1321,14 @@ describe "an Active Record model which includes PgSearch" do
1305
1321
  context "when using the dmetaphone ranking algorithm" do
1306
1322
  it "sorts results by the dmetaphone rank" do
1307
1323
  ModelWithPgSearch.pg_search_scope :search_content_ranked_by_dmetaphone,
1308
- using: :dmetaphone,
1309
- against: :content,
1310
- ranked_by: ":dmetaphone"
1324
+ using: :dmetaphone,
1325
+ against: :content,
1326
+ ranked_by: ":dmetaphone"
1311
1327
 
1312
- once = ModelWithPgSearch.create!(content: 'Phoo Bar')
1313
- twice = ModelWithPgSearch.create!(content: 'Phoo Fu')
1328
+ once = ModelWithPgSearch.create!(content: "Phoo Bar")
1329
+ twice = ModelWithPgSearch.create!(content: "Phoo Fu")
1314
1330
 
1315
- results = ModelWithPgSearch.search_content_ranked_by_dmetaphone('foo')
1331
+ results = ModelWithPgSearch.search_content_ranked_by_dmetaphone("foo")
1316
1332
  expect(results.find_index(twice)).to be < results.find_index(once)
1317
1333
  end
1318
1334
  end
@@ -1321,17 +1337,17 @@ describe "an Active Record model which includes PgSearch" do
1321
1337
  context "when there is a sort only feature" do
1322
1338
  it "excludes that feature from the conditions, but uses it in the sorting" do
1323
1339
  ModelWithPgSearch.pg_search_scope :search_content_ranked_by_dmetaphone,
1324
- against: :content,
1325
- using: {
1326
- tsearch: { any_word: true, prefix: true },
1327
- dmetaphone: { any_word: true, prefix: true, sort_only: true }
1328
- },
1329
- ranked_by: ":tsearch + (0.5 * :dmetaphone)"
1340
+ against: :content,
1341
+ using: {
1342
+ tsearch: {any_word: true, prefix: true},
1343
+ dmetaphone: {any_word: true, prefix: true, sort_only: true}
1344
+ },
1345
+ ranked_by: ":tsearch + (0.5 * :dmetaphone)"
1330
1346
 
1331
1347
  exact = ModelWithPgSearch.create!(content: "ash hines")
1332
1348
  one_exact_one_close = ModelWithPgSearch.create!(content: "ash heinz")
1333
1349
  one_exact = ModelWithPgSearch.create!(content: "ash smith")
1334
- one_close = ModelWithPgSearch.create!(content: "leigh heinz")
1350
+ ModelWithPgSearch.create!(content: "leigh heinz")
1335
1351
 
1336
1352
  results = ModelWithPgSearch.search_content_ranked_by_dmetaphone("ash hines")
1337
1353
  expect(results).to eq [exact, one_exact_one_close, one_exact]
@@ -1339,4 +1355,4 @@ describe "an Active Record model which includes PgSearch" do
1339
1355
  end
1340
1356
  end
1341
1357
  end
1342
- # rubocop:enable RSpec/NestedGroups
1358
+ # standard:enable RSpec/NestedGroups