pg_search 0.7.4 → 0.7.5
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/CHANGELOG.md +4 -0
- data/README.md +30 -13
- data/lib/pg_search/document.rb +4 -2
- data/lib/pg_search/features/tsearch.rb +23 -19
- data/lib/pg_search/migration/associated_against_generator.rb +4 -16
- data/lib/pg_search/migration/dmetaphone_generator.rb +4 -16
- data/lib/pg_search/migration/generator.rb +28 -0
- data/lib/pg_search/migration/multisearch_generator.rb +4 -8
- data/lib/pg_search/migration/templates/add_pg_search_associated_against_support_functions.rb.erb +2 -2
- data/lib/pg_search/migration/templates/{create_pg_search_documents.rb → create_pg_search_documents.rb.erb} +0 -0
- data/lib/pg_search/scope_options.rb +3 -1
- data/lib/pg_search/version.rb +1 -1
- data/pg_search.gemspec +1 -1
- data/spec/integration/associations_spec.rb +25 -25
- data/spec/integration/pagination_spec.rb +4 -4
- data/spec/integration/pg_search_spec.rb +123 -103
- data/spec/lib/pg_search/configuration/column_spec.rb +2 -2
- data/spec/lib/pg_search/document_spec.rb +11 -4
- data/spec/lib/pg_search/features/dmetaphone_spec.rb +4 -2
- data/spec/lib/pg_search/features/tsearch_spec.rb +4 -2
- data/spec/lib/pg_search/multisearch/rebuilder_spec.rb +16 -16
- data/spec/lib/pg_search/multisearch_spec.rb +15 -18
- data/spec/lib/pg_search/multisearchable_spec.rb +39 -38
- data/spec/lib/pg_search/normalizer_spec.rb +8 -8
- data/spec/spec_helper.rb +8 -94
- data/spec/support/coveralls.rb +7 -0
- data/spec/support/database.rb +83 -0
- data/spec/support/with_model.rb +5 -0
- metadata +14 -7
@@ -17,7 +17,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
17
17
|
it "builds a chainable scope" do
|
18
18
|
ModelWithPgSearch.pg_search_scope "matching_query", :against => []
|
19
19
|
scope = ModelWithPgSearch.where("1 = 1").matching_query("foo").where("1 = 1")
|
20
|
-
scope.
|
20
|
+
expect(scope).to be_an ActiveRecord::Relation
|
21
21
|
end
|
22
22
|
|
23
23
|
context "when passed a lambda" do
|
@@ -33,8 +33,8 @@ describe "an Active Record model which includes PgSearch" do
|
|
33
33
|
included = ModelWithPgSearch.create!(:title => 'foo', :content => 'bar')
|
34
34
|
excluded = ModelWithPgSearch.create!(:title => 'bar', :content => 'foo')
|
35
35
|
|
36
|
-
ModelWithPgSearch.search_title_or_content('fo-remove-o', false).
|
37
|
-
ModelWithPgSearch.search_title_or_content('b-remove-ar', true).
|
36
|
+
expect(ModelWithPgSearch.search_title_or_content('fo-remove-o', false)).to eq([included])
|
37
|
+
expect(ModelWithPgSearch.search_title_or_content('b-remove-ar', true)).to eq([included])
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
@@ -139,7 +139,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
139
139
|
ModelWithPgSearch.create!(:content => 'foo')
|
140
140
|
|
141
141
|
results = ModelWithPgSearch.search_content('')
|
142
|
-
results.
|
142
|
+
expect(results).to eq([])
|
143
143
|
end
|
144
144
|
|
145
145
|
it "returns rows where the column contains the term in the query" do
|
@@ -147,8 +147,8 @@ describe "an Active Record model which includes PgSearch" do
|
|
147
147
|
excluded = ModelWithPgSearch.create!(:content => 'bar')
|
148
148
|
|
149
149
|
results = ModelWithPgSearch.search_content('foo')
|
150
|
-
results.
|
151
|
-
results.
|
150
|
+
expect(results).to include(included)
|
151
|
+
expect(results).not_to include(excluded)
|
152
152
|
end
|
153
153
|
|
154
154
|
it "returns the correct count" do
|
@@ -165,8 +165,8 @@ describe "an Active Record model which includes PgSearch" do
|
|
165
165
|
excluded = ModelWithPgSearch.create!(:content => 'foo')
|
166
166
|
|
167
167
|
results = ModelWithPgSearch.search_content('foo bar')
|
168
|
-
results.
|
169
|
-
results.
|
168
|
+
expect(results).to match_array(included)
|
169
|
+
expect(results).not_to include(excluded)
|
170
170
|
end
|
171
171
|
|
172
172
|
it "returns rows that match the query but not its case" do
|
@@ -174,7 +174,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
174
174
|
ModelWithPgSearch.create!(:content => "FOO")]
|
175
175
|
|
176
176
|
results = ModelWithPgSearch.search_content("Foo")
|
177
|
-
results.
|
177
|
+
expect(results).to match_array(included)
|
178
178
|
end
|
179
179
|
|
180
180
|
it "returns rows that match the query only if their accents match" do
|
@@ -185,8 +185,8 @@ describe "an Active Record model which includes PgSearch" do
|
|
185
185
|
excluded = ModelWithPgSearch.create!(:content => "\303\241bcdef")
|
186
186
|
|
187
187
|
results = ModelWithPgSearch.search_content("abcd\303\251f")
|
188
|
-
results.
|
189
|
-
results.
|
188
|
+
expect(results).to eq([included])
|
189
|
+
expect(results).not_to include(excluded)
|
190
190
|
end
|
191
191
|
|
192
192
|
it "returns rows that match the query but not rows that are prefixed by the query" do
|
@@ -194,8 +194,8 @@ describe "an Active Record model which includes PgSearch" do
|
|
194
194
|
excluded = ModelWithPgSearch.create!(:content => 'prefix')
|
195
195
|
|
196
196
|
results = ModelWithPgSearch.search_content("pre")
|
197
|
-
results.
|
198
|
-
results.
|
197
|
+
expect(results).to eq([included])
|
198
|
+
expect(results).not_to include(excluded)
|
199
199
|
end
|
200
200
|
|
201
201
|
it "returns rows that match the query exactly and not those that match the query when stemmed by the default english dictionary" do
|
@@ -204,7 +204,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
204
204
|
ModelWithPgSearch.create!(:content => "jumping")]
|
205
205
|
|
206
206
|
results = ModelWithPgSearch.search_content("jumped")
|
207
|
-
results.
|
207
|
+
expect(results).to eq([included])
|
208
208
|
end
|
209
209
|
|
210
210
|
it "returns rows that match sorted by rank" do
|
@@ -212,8 +212,8 @@ describe "an Active Record model which includes PgSearch" do
|
|
212
212
|
winner = ModelWithPgSearch.create!(:content => 'foo foo')
|
213
213
|
|
214
214
|
results = ModelWithPgSearch.search_content("foo")
|
215
|
-
results[0].pg_search_rank.
|
216
|
-
results.
|
215
|
+
expect(results[0].pg_search_rank).to be > results[1].pg_search_rank
|
216
|
+
expect(results).to eq([winner, loser])
|
217
217
|
end
|
218
218
|
|
219
219
|
it "returns results that match sorted by primary key for records that rank the same" do
|
@@ -221,7 +221,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
221
221
|
ModelWithPgSearch.create!(:content => 'foo')].sort_by(&:id)
|
222
222
|
|
223
223
|
results = ModelWithPgSearch.search_content("foo")
|
224
|
-
results.
|
224
|
+
expect(results).to eq(sorted_results)
|
225
225
|
end
|
226
226
|
|
227
227
|
it "returns results that match a query with multiple space-separated search terms" do
|
@@ -236,21 +236,21 @@ describe "an Active Record model which includes PgSearch" do
|
|
236
236
|
]
|
237
237
|
|
238
238
|
results = ModelWithPgSearch.search_content('foo bar')
|
239
|
-
results.
|
240
|
-
results.
|
239
|
+
expect(results).to match_array(included)
|
240
|
+
expect(results).not_to include(excluded)
|
241
241
|
end
|
242
242
|
|
243
243
|
it "returns rows that match a query with characters that are invalid in a tsquery expression" do
|
244
244
|
included = ModelWithPgSearch.create!(:content => "(:Foo.) Bar?, \\")
|
245
245
|
|
246
246
|
results = ModelWithPgSearch.search_content("foo :bar .,?() \\")
|
247
|
-
results.
|
247
|
+
expect(results).to eq([included])
|
248
248
|
end
|
249
249
|
|
250
250
|
it "accepts non-string queries and calls #to_s on them" do
|
251
251
|
foo = ModelWithPgSearch.create!(:content => "foo")
|
252
252
|
not_a_string = double(:to_s => "foo")
|
253
|
-
ModelWithPgSearch.search_content(not_a_string).
|
253
|
+
expect(ModelWithPgSearch.search_content(not_a_string)).to eq([foo])
|
254
254
|
end
|
255
255
|
|
256
256
|
context "when the column is not text" do
|
@@ -274,7 +274,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
274
274
|
|
275
275
|
query = record.created_at.strftime("%Y-%m-%d")
|
276
276
|
results = ModelWithTimestamps.search_timestamps(query)
|
277
|
-
results.
|
277
|
+
expect(results).to eq([record])
|
278
278
|
end
|
279
279
|
end
|
280
280
|
end
|
@@ -296,9 +296,9 @@ describe "an Active Record model which includes PgSearch" do
|
|
296
296
|
|
297
297
|
results = ModelWithPgSearch.search_title_and_content('foo bar')
|
298
298
|
|
299
|
-
results.
|
299
|
+
expect(results).to match_array(included)
|
300
300
|
excluded.each do |result|
|
301
|
-
results.
|
301
|
+
expect(results).not_to include(result)
|
302
302
|
end
|
303
303
|
end
|
304
304
|
|
@@ -307,14 +307,14 @@ describe "an Active Record model which includes PgSearch" do
|
|
307
307
|
in_content = ModelWithPgSearch.create!(:title => 'bar', :content => 'foo')
|
308
308
|
|
309
309
|
results = ModelWithPgSearch.search_title_and_content('foo')
|
310
|
-
results.
|
310
|
+
expect(results).to match_array([in_title, in_content])
|
311
311
|
end
|
312
312
|
|
313
313
|
# Searching with a NULL column will prevent any matches unless we coalesce it.
|
314
314
|
it "returns rows where at one column contains all of the terms in the query and another is NULL" do
|
315
315
|
included = ModelWithPgSearch.create!(:title => 'foo', :content => nil)
|
316
316
|
results = ModelWithPgSearch.search_title_and_content('foo')
|
317
|
-
results.
|
317
|
+
expect(results).to eq([included])
|
318
318
|
end
|
319
319
|
end
|
320
320
|
|
@@ -326,13 +326,13 @@ describe "an Active Record model which includes PgSearch" do
|
|
326
326
|
it "returns rows where one searchable column and the query share enough trigrams" do
|
327
327
|
included = ModelWithPgSearch.create!(:title => 'abcdefghijkl', :content => nil)
|
328
328
|
results = ModelWithPgSearch.with_trigrams('cdefhijkl')
|
329
|
-
results.
|
329
|
+
expect(results).to eq([included])
|
330
330
|
end
|
331
331
|
|
332
332
|
it "returns rows where multiple searchable columns and the query share enough trigrams" do
|
333
333
|
included = ModelWithPgSearch.create!(:title => 'abcdef', :content => 'ghijkl')
|
334
334
|
results = ModelWithPgSearch.with_trigrams('cdefhijkl')
|
335
|
-
results.
|
335
|
+
expect(results).to eq([included])
|
336
336
|
end
|
337
337
|
|
338
338
|
context "when a threshold is specified" do
|
@@ -382,8 +382,8 @@ describe "an Active Record model which includes PgSearch" do
|
|
382
382
|
excluded = ModelWithPgSearch.create!(:title => 'postfix')
|
383
383
|
|
384
384
|
results = ModelWithPgSearch.search_title_with_prefixes("pre")
|
385
|
-
results.
|
386
|
-
results.
|
385
|
+
expect(results).to eq([included])
|
386
|
+
expect(results).not_to include(excluded)
|
387
387
|
end
|
388
388
|
|
389
389
|
it "returns rows that match the query when the query has a hyphen" do
|
@@ -391,8 +391,8 @@ describe "an Active Record model which includes PgSearch" do
|
|
391
391
|
excluded = ModelWithPgSearch.create!(:title => 'foo bar')
|
392
392
|
|
393
393
|
results = ModelWithPgSearch.search_title_with_prefixes("foo-bar")
|
394
|
-
results.
|
395
|
-
results.
|
394
|
+
expect(results).to include(included)
|
395
|
+
expect(results).not_to include(excluded)
|
396
396
|
end
|
397
397
|
end
|
398
398
|
end
|
@@ -412,7 +412,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
412
412
|
ModelWithPgSearch.create!(:content => "jumping")]
|
413
413
|
|
414
414
|
results = ModelWithPgSearch.search_content_with_english("jump")
|
415
|
-
results.
|
415
|
+
expect(results).to match_array(included)
|
416
416
|
end
|
417
417
|
end
|
418
418
|
|
@@ -428,7 +428,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
428
428
|
|
429
429
|
result = ModelWithPgSearch.search_content("Strip Down").first
|
430
430
|
|
431
|
-
result.pg_search_rank.
|
431
|
+
expect(result.pg_search_rank).to be_a(Float)
|
432
432
|
end
|
433
433
|
|
434
434
|
context "with a normalization specified" do
|
@@ -443,8 +443,8 @@ describe "an Active Record model which includes PgSearch" do
|
|
443
443
|
it "ranks the results for documents with less text higher" do
|
444
444
|
results = ModelWithPgSearch.search_content_with_normalization("down")
|
445
445
|
|
446
|
-
results.map(&:content).
|
447
|
-
results.first.pg_search_rank.
|
446
|
+
expect(results.map(&:content)).to eq(["Down", "Strip Down", "Down and Out", "Won't Let You Down"])
|
447
|
+
expect(results.first.pg_search_rank).to be > results.last.pg_search_rank
|
448
448
|
end
|
449
449
|
end
|
450
450
|
|
@@ -458,8 +458,8 @@ describe "an Active Record model which includes PgSearch" do
|
|
458
458
|
it "ranks the results equally" do
|
459
459
|
results = ModelWithPgSearch.search_content_without_normalization("down")
|
460
460
|
|
461
|
-
results.map(&:content).
|
462
|
-
results.first.pg_search_rank.
|
461
|
+
expect(results.map(&:content)).to eq(["Strip Down", "Down", "Down and Out", "Won't Let You Down"])
|
462
|
+
expect(results.first.pg_search_rank).to eq(results.last.pg_search_rank)
|
463
463
|
end
|
464
464
|
end
|
465
465
|
end
|
@@ -475,8 +475,8 @@ describe "an Active Record model which includes PgSearch" do
|
|
475
475
|
winner = ModelWithPgSearch.create!(:title => 'foo', :content => 'bar')
|
476
476
|
|
477
477
|
results = ModelWithPgSearch.search_weighted_by_array_of_arrays('foo')
|
478
|
-
results[0].pg_search_rank.
|
479
|
-
results.
|
478
|
+
expect(results[0].pg_search_rank).to be > results[1].pg_search_rank
|
479
|
+
expect(results).to eq([winner, loser])
|
480
480
|
end
|
481
481
|
end
|
482
482
|
|
@@ -491,8 +491,8 @@ describe "an Active Record model which includes PgSearch" do
|
|
491
491
|
winner = ModelWithPgSearch.create!(:title => 'foo', :content => 'bar')
|
492
492
|
|
493
493
|
results = ModelWithPgSearch.search_weighted_by_hash('foo')
|
494
|
-
results[0].pg_search_rank.
|
495
|
-
results.
|
494
|
+
expect(results[0].pg_search_rank).to be > results[1].pg_search_rank
|
495
|
+
expect(results).to eq([winner, loser])
|
496
496
|
end
|
497
497
|
end
|
498
498
|
|
@@ -507,8 +507,8 @@ describe "an Active Record model which includes PgSearch" do
|
|
507
507
|
winner = ModelWithPgSearch.create!(:title => 'foo', :content => 'bar')
|
508
508
|
|
509
509
|
results = ModelWithPgSearch.search_weighted('foo')
|
510
|
-
results[0].pg_search_rank.
|
511
|
-
results.
|
510
|
+
expect(results[0].pg_search_rank).to be > results[1].pg_search_rank
|
511
|
+
expect(results).to eq([winner, loser])
|
512
512
|
end
|
513
513
|
end
|
514
514
|
|
@@ -529,11 +529,11 @@ describe "an Active Record model which includes PgSearch" do
|
|
529
529
|
|
530
530
|
results = ModelWithPgSearch.search_title_with_any_word("one two three four")
|
531
531
|
|
532
|
-
results.map(&:title).
|
532
|
+
expect(results.map(&:title)).to eq(%w(one two three four))
|
533
533
|
|
534
534
|
results = ModelWithPgSearch.search_title_with_all_words("one two three four")
|
535
535
|
|
536
|
-
results.map(&:title).
|
536
|
+
expect(results.map(&:title)).to eq([])
|
537
537
|
end
|
538
538
|
end
|
539
539
|
end
|
@@ -549,21 +549,21 @@ describe "an Active Record model which includes PgSearch" do
|
|
549
549
|
included = ModelWithPgSearch.create!(:title => 'Geoff', :content => nil)
|
550
550
|
excluded = ModelWithPgSearch.create!(:title => 'Bob', :content => nil)
|
551
551
|
results = ModelWithPgSearch.with_dmetaphones('Jeff')
|
552
|
-
results.
|
552
|
+
expect(results).to eq([included])
|
553
553
|
end
|
554
554
|
|
555
555
|
it "returns rows where multiple searchable columns and the query share enough dmetaphones" do
|
556
556
|
included = ModelWithPgSearch.create!(:title => 'Geoff', :content => 'George')
|
557
557
|
excluded = ModelWithPgSearch.create!(:title => 'Bob', :content => 'Jones')
|
558
558
|
results = ModelWithPgSearch.with_dmetaphones('Jeff Jorge')
|
559
|
-
results.
|
559
|
+
expect(results).to eq([included])
|
560
560
|
end
|
561
561
|
|
562
562
|
it "returns rows that match dmetaphones that are English stopwords" do
|
563
563
|
included = ModelWithPgSearch.create!(:title => 'White', :content => nil)
|
564
564
|
excluded = ModelWithPgSearch.create!(:title => 'Black', :content => nil)
|
565
565
|
results = ModelWithPgSearch.with_dmetaphones('Wight')
|
566
|
-
results.
|
566
|
+
expect(results).to eq([included])
|
567
567
|
end
|
568
568
|
|
569
569
|
it "can handle terms that do not have a dmetaphone equivalent" do
|
@@ -573,7 +573,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
573
573
|
excluded = ModelWithPgSearch.create!(:title => 'Black', :content => nil)
|
574
574
|
|
575
575
|
results = ModelWithPgSearch.with_dmetaphones('Wight W')
|
576
|
-
results.
|
576
|
+
expect(results).to eq([included])
|
577
577
|
end
|
578
578
|
end
|
579
579
|
|
@@ -616,37 +616,37 @@ describe "an Active Record model which includes PgSearch" do
|
|
616
616
|
|
617
617
|
# matches trigram only
|
618
618
|
trigram_query = "ling is grouty"
|
619
|
-
ModelWithPgSearch.with_trigram(trigram_query).
|
620
|
-
ModelWithPgSearch.with_trigram_and_ignoring_accents(trigram_query).
|
621
|
-
ModelWithPgSearch.with_tsearch(trigram_query).
|
622
|
-
ModelWithPgSearch.with_tsearch_and_trigram(trigram_query).
|
623
|
-
ModelWithPgSearch.complex_search(trigram_query).
|
619
|
+
expect(ModelWithPgSearch.with_trigram(trigram_query)).to include(record)
|
620
|
+
expect(ModelWithPgSearch.with_trigram_and_ignoring_accents(trigram_query)).to include(record)
|
621
|
+
expect(ModelWithPgSearch.with_tsearch(trigram_query)).not_to include(record)
|
622
|
+
expect(ModelWithPgSearch.with_tsearch_and_trigram(trigram_query)).to eq([record])
|
623
|
+
expect(ModelWithPgSearch.complex_search(trigram_query)).to include(record)
|
624
624
|
|
625
625
|
# matches accent
|
626
626
|
# \303\266 is o with diaeresis
|
627
627
|
# \303\272 is u with acute accent
|
628
628
|
accent_query = "gr\303\266\303\272ty"
|
629
|
-
ModelWithPgSearch.with_trigram(accent_query).
|
630
|
-
ModelWithPgSearch.with_trigram_and_ignoring_accents(accent_query).
|
631
|
-
ModelWithPgSearch.with_tsearch(accent_query).
|
632
|
-
ModelWithPgSearch.with_tsearch_and_trigram(accent_query).count(:all).
|
633
|
-
ModelWithPgSearch.complex_search(accent_query).
|
629
|
+
expect(ModelWithPgSearch.with_trigram(accent_query)).not_to include(record)
|
630
|
+
expect(ModelWithPgSearch.with_trigram_and_ignoring_accents(accent_query)).to include(record)
|
631
|
+
expect(ModelWithPgSearch.with_tsearch(accent_query)).not_to include(record)
|
632
|
+
expect(ModelWithPgSearch.with_tsearch_and_trigram(accent_query).count(:all)).to eq(0)
|
633
|
+
expect(ModelWithPgSearch.complex_search(accent_query)).to include(record)
|
634
634
|
|
635
635
|
# matches tsearch only
|
636
636
|
tsearch_query = "tiles"
|
637
|
-
ModelWithPgSearch.with_tsearch(tsearch_query).
|
638
|
-
ModelWithPgSearch.with_trigram(tsearch_query).
|
639
|
-
ModelWithPgSearch.with_trigram_and_ignoring_accents(tsearch_query).
|
640
|
-
ModelWithPgSearch.with_tsearch_and_trigram(tsearch_query).
|
641
|
-
ModelWithPgSearch.complex_search(tsearch_query).
|
637
|
+
expect(ModelWithPgSearch.with_tsearch(tsearch_query)).to include(record)
|
638
|
+
expect(ModelWithPgSearch.with_trigram(tsearch_query)).not_to include(record)
|
639
|
+
expect(ModelWithPgSearch.with_trigram_and_ignoring_accents(tsearch_query)).not_to include(record)
|
640
|
+
expect(ModelWithPgSearch.with_tsearch_and_trigram(tsearch_query)).to eq([record])
|
641
|
+
expect(ModelWithPgSearch.complex_search(tsearch_query)).to include(record)
|
642
642
|
|
643
643
|
# matches dmetaphone only
|
644
644
|
dmetaphone_query = "tyling"
|
645
|
-
ModelWithPgSearch.with_tsearch(dmetaphone_query).
|
646
|
-
ModelWithPgSearch.with_trigram(dmetaphone_query).
|
647
|
-
ModelWithPgSearch.with_trigram_and_ignoring_accents(dmetaphone_query).
|
648
|
-
ModelWithPgSearch.with_tsearch_and_trigram(dmetaphone_query).
|
649
|
-
ModelWithPgSearch.complex_search(dmetaphone_query).
|
645
|
+
expect(ModelWithPgSearch.with_tsearch(dmetaphone_query)).not_to include(record)
|
646
|
+
expect(ModelWithPgSearch.with_trigram(dmetaphone_query)).not_to include(record)
|
647
|
+
expect(ModelWithPgSearch.with_trigram_and_ignoring_accents(dmetaphone_query)).not_to include(record)
|
648
|
+
expect(ModelWithPgSearch.with_tsearch_and_trigram(dmetaphone_query)).not_to include(record)
|
649
|
+
expect(ModelWithPgSearch.complex_search(dmetaphone_query)).to include(record)
|
650
650
|
end
|
651
651
|
|
652
652
|
context "with feature-specific configuration" do
|
@@ -668,8 +668,8 @@ describe "an Active Record model which includes PgSearch" do
|
|
668
668
|
:rank => Arel::Nodes::Grouping.new(Arel.sql("1.0"))
|
669
669
|
)
|
670
670
|
|
671
|
-
PgSearch::Features::TSearch.
|
672
|
-
PgSearch::Features::Trigram.
|
671
|
+
expect(PgSearch::Features::TSearch).to receive(:new).with(anything, @tsearch_config, anything, anything, anything).at_least(:once).and_return(stub_feature)
|
672
|
+
expect(PgSearch::Features::Trigram).to receive(:new).with(anything, @trigram_config, anything, anything, anything).at_least(:once).and_return(stub_feature)
|
673
673
|
|
674
674
|
ModelWithPgSearch.with_tsearch_and_trigram_using_hash("foo")
|
675
675
|
end
|
@@ -723,15 +723,15 @@ describe "an Active Record model which includes PgSearch" do
|
|
723
723
|
end
|
724
724
|
|
725
725
|
it "should find by the tsvector column" do
|
726
|
-
Post.search_by_content_with_tsvector("phooey").map(&:id).
|
726
|
+
expect(Post.search_by_content_with_tsvector("phooey").map(&:id)).to eq([expected.id])
|
727
727
|
end
|
728
728
|
|
729
729
|
it "should find by the associated record" do
|
730
|
-
Post.search_by_content_with_tsvector("commentone").map(&:id).
|
730
|
+
expect(Post.search_by_content_with_tsvector("commentone").map(&:id)).to eq([expected.id])
|
731
731
|
end
|
732
732
|
|
733
733
|
it 'should find by a combination of the two' do
|
734
|
-
Post.search_by_content_with_tsvector("phooey commentone").map(&:id).
|
734
|
+
expect(Post.search_by_content_with_tsvector("phooey commentone").map(&:id)).to eq([expected.id])
|
735
735
|
end
|
736
736
|
end
|
737
737
|
|
@@ -765,11 +765,11 @@ describe "an Active Record model which includes PgSearch" do
|
|
765
765
|
end
|
766
766
|
|
767
767
|
it "should not use to_tsvector in the query" do
|
768
|
-
ModelWithTsvector.search_by_content_with_tsvector("tiles").to_sql.
|
768
|
+
expect(ModelWithTsvector.search_by_content_with_tsvector("tiles").to_sql).not_to match(/to_tsvector/)
|
769
769
|
end
|
770
770
|
|
771
771
|
it "should find the expected result" do
|
772
|
-
ModelWithTsvector.search_by_content_with_tsvector("tiles").map(&:id).
|
772
|
+
expect(ModelWithTsvector.search_by_content_with_tsvector("tiles").map(&:id)).to eq([expected.id])
|
773
773
|
end
|
774
774
|
|
775
775
|
context "when joining to a table with a column of the same name" do
|
@@ -813,7 +813,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
813
813
|
included = ModelWithPgSearch.create!(:title => "\303\241bcdef")
|
814
814
|
|
815
815
|
results = ModelWithPgSearch.search_title_without_accents("abcd\303\251f")
|
816
|
-
results.
|
816
|
+
expect(results).to eq([included])
|
817
817
|
end
|
818
818
|
end
|
819
819
|
end
|
@@ -835,7 +835,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
835
835
|
it "should return records with a rank attribute equal to the :ranked_by expression" do
|
836
836
|
ModelWithPgSearch.create!(:content => 'foo', :importance => 10)
|
837
837
|
results = ModelWithPgSearch.search_content_with_importance_as_rank("foo")
|
838
|
-
results.first.pg_search_rank.
|
838
|
+
expect(results.first.pg_search_rank).to eq(10)
|
839
839
|
end
|
840
840
|
|
841
841
|
it "should substitute :tsearch with the tsearch rank expression in the :ranked_by expression" do
|
@@ -844,7 +844,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
844
844
|
tsearch_rank = ModelWithPgSearch.search_content_with_default_rank("foo").first.pg_search_rank
|
845
845
|
multiplied_rank = ModelWithPgSearch.search_content_with_importance_as_rank_multiplier("foo").first.pg_search_rank
|
846
846
|
|
847
|
-
multiplied_rank.
|
847
|
+
expect(multiplied_rank).to be_within(0.001).of(tsearch_rank * 10)
|
848
848
|
end
|
849
849
|
|
850
850
|
it "should return results in descending order of the value of the rank expression" do
|
@@ -855,7 +855,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
855
855
|
]
|
856
856
|
|
857
857
|
results = ModelWithPgSearch.search_content_with_importance_as_rank("foo")
|
858
|
-
results.
|
858
|
+
expect(results).to eq(records.sort_by(&:importance).reverse)
|
859
859
|
end
|
860
860
|
|
861
861
|
%w[tsearch trigram dmetaphone].each do |feature|
|
@@ -870,7 +870,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
870
870
|
ModelWithPgSearch.create!(:content => 'foo')
|
871
871
|
|
872
872
|
results = ModelWithPgSearch.send(scope_name, 'foo')
|
873
|
-
results.first.pg_search_rank.
|
873
|
+
expect(results.first.pg_search_rank).to be_a Float
|
874
874
|
end
|
875
875
|
end
|
876
876
|
end
|
@@ -887,7 +887,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
887
887
|
twice = ModelWithPgSearch.create!(:content => 'foo foo')
|
888
888
|
|
889
889
|
results = ModelWithPgSearch.search_content_ranked_by_tsearch('foo')
|
890
|
-
results.index(twice).
|
890
|
+
expect(results.index(twice)).to be < results.index(once)
|
891
891
|
end
|
892
892
|
end
|
893
893
|
|
@@ -902,7 +902,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
902
902
|
exact = ModelWithPgSearch.create!(:content => 'abc')
|
903
903
|
|
904
904
|
results = ModelWithPgSearch.search_content_ranked_by_trigram('abc')
|
905
|
-
results.index(exact).
|
905
|
+
expect(results.index(exact)).to be < results.index(close)
|
906
906
|
end
|
907
907
|
end
|
908
908
|
|
@@ -917,7 +917,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
917
917
|
twice = ModelWithPgSearch.create!(:content => 'Phoo Fu')
|
918
918
|
|
919
919
|
results = ModelWithPgSearch.search_content_ranked_by_dmetaphone('foo')
|
920
|
-
results.index(twice).
|
920
|
+
expect(results.index(twice)).to be < results.index(once)
|
921
921
|
end
|
922
922
|
end
|
923
923
|
end
|
@@ -956,27 +956,47 @@ describe "an Active Record model which includes PgSearch" do
|
|
956
956
|
AnotherSubclassModel.create!(:content => "baz")
|
957
957
|
]
|
958
958
|
|
959
|
-
SuperclassModel.count.
|
960
|
-
SubclassModel.count.
|
959
|
+
expect(SuperclassModel.count).to eq(6)
|
960
|
+
expect(SubclassModel.count).to eq(2)
|
961
961
|
|
962
962
|
results = SubclassModel.search_content("foo bar")
|
963
963
|
|
964
|
-
results.
|
965
|
-
results.
|
964
|
+
expect(results).to include(*included)
|
965
|
+
expect(results).not_to include(*excluded)
|
966
|
+
end
|
967
|
+
end
|
968
|
+
|
969
|
+
context "when there is a sort only feature" do
|
970
|
+
it "excludes that feature from the conditions, but uses it in the sorting" do
|
971
|
+
ModelWithPgSearch.pg_search_scope :search_content_ranked_by_dmetaphone,
|
972
|
+
:against => :content,
|
973
|
+
:using => {
|
974
|
+
:tsearch => { :any_word => true, :prefix => true },
|
975
|
+
:dmetaphone => { :any_word => true, :prefix => true, :sort_only => true }
|
976
|
+
},
|
977
|
+
:ranked_by => ":tsearch + (0.5 * :dmetaphone)"
|
978
|
+
|
979
|
+
exact = ModelWithPgSearch.create!(:content => "ash hines")
|
980
|
+
one_exact_one_close = ModelWithPgSearch.create!(:content => "ash heinz")
|
981
|
+
one_exact = ModelWithPgSearch.create!(:content => "ash smith")
|
982
|
+
one_close = ModelWithPgSearch.create!(:content => "leigh heinz")
|
983
|
+
|
984
|
+
results = ModelWithPgSearch.search_content_ranked_by_dmetaphone("ash hines")
|
985
|
+
expect(results).to eq [exact, one_exact_one_close, one_exact]
|
966
986
|
end
|
967
987
|
end
|
968
988
|
end
|
969
989
|
|
970
990
|
describe ".multisearchable" do
|
971
991
|
it "should include the Multisearchable module" do
|
972
|
-
ModelWithPgSearch.
|
992
|
+
expect(ModelWithPgSearch).to receive(:include).with(PgSearch::Multisearchable)
|
973
993
|
ModelWithPgSearch.multisearchable
|
974
994
|
end
|
975
995
|
|
976
996
|
it "should set pg_search_multisearchable_options on the class" do
|
977
997
|
options = double(:options)
|
978
998
|
ModelWithPgSearch.multisearchable(options)
|
979
|
-
ModelWithPgSearch.pg_search_multisearchable_options.
|
999
|
+
expect(ModelWithPgSearch.pg_search_multisearchable_options).to eq(options)
|
980
1000
|
end
|
981
1001
|
end
|
982
1002
|
|
@@ -989,14 +1009,14 @@ describe "an Active Record model which includes PgSearch" do
|
|
989
1009
|
let(:query) { double(:query) }
|
990
1010
|
let(:relation) { double(:relation) }
|
991
1011
|
before do
|
992
|
-
PgSearch::Document.
|
1012
|
+
expect(PgSearch::Document).to receive(:search).with(query).and_return(relation)
|
993
1013
|
end
|
994
1014
|
|
995
1015
|
it { should == relation }
|
996
1016
|
end
|
997
1017
|
|
998
1018
|
context "with PgSearch.multisearch_options set to a Hash" do
|
999
|
-
before { PgSearch.
|
1019
|
+
before { allow(PgSearch).to receive(:multisearch_options).and_return({:using => :dmetaphone}) }
|
1000
1020
|
subject { PgSearch.multisearch(query).map(&:searchable) }
|
1001
1021
|
|
1002
1022
|
with_model :MultisearchableModel do
|
@@ -1018,7 +1038,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
1018
1038
|
subject { PgSearch.multisearch(query, soundalike).map(&:searchable) }
|
1019
1039
|
|
1020
1040
|
before do
|
1021
|
-
PgSearch.
|
1041
|
+
allow(PgSearch).to receive(:multisearch_options) do
|
1022
1042
|
lambda do |query, soundalike|
|
1023
1043
|
if soundalike
|
1024
1044
|
{:using => :dmetaphone, :query => query}
|
@@ -1105,9 +1125,9 @@ describe "an Active Record model which includes PgSearch" do
|
|
1105
1125
|
end
|
1106
1126
|
@multisearch_enabled_after = PgSearch.multisearch_enabled?
|
1107
1127
|
|
1108
|
-
@multisearch_enabled_before.
|
1109
|
-
@multisearch_enabled_inside.
|
1110
|
-
@multisearch_enabled_after.
|
1128
|
+
expect(@multisearch_enabled_before).to be(true)
|
1129
|
+
expect(@multisearch_enabled_inside).to be(false)
|
1130
|
+
expect(@multisearch_enabled_after).to be(true)
|
1111
1131
|
end
|
1112
1132
|
|
1113
1133
|
it "should reenable multisearch after an error" do
|
@@ -1122,9 +1142,9 @@ describe "an Active Record model which includes PgSearch" do
|
|
1122
1142
|
|
1123
1143
|
@multisearch_enabled_after = PgSearch.multisearch_enabled?
|
1124
1144
|
|
1125
|
-
@multisearch_enabled_before.
|
1126
|
-
@multisearch_enabled_inside.
|
1127
|
-
@multisearch_enabled_after.
|
1145
|
+
expect(@multisearch_enabled_before).to be(true)
|
1146
|
+
expect(@multisearch_enabled_inside).to be(false)
|
1147
|
+
expect(@multisearch_enabled_after).to be(true)
|
1128
1148
|
end
|
1129
1149
|
|
1130
1150
|
it "should not disable multisearch on other threads" do
|
@@ -1146,9 +1166,9 @@ describe "an Active Record model which includes PgSearch" do
|
|
1146
1166
|
sync.push :go
|
1147
1167
|
@multisearch_enabled_after = values.pop
|
1148
1168
|
|
1149
|
-
@multisearch_enabled_before.
|
1150
|
-
@multisearch_enabled_inside.
|
1151
|
-
@multisearch_enabled_after.
|
1169
|
+
expect(@multisearch_enabled_before).to be(true)
|
1170
|
+
expect(@multisearch_enabled_inside).to be(true)
|
1171
|
+
expect(@multisearch_enabled_after).to be(true)
|
1152
1172
|
end
|
1153
1173
|
end
|
1154
1174
|
end
|
@@ -10,7 +10,7 @@ describe PgSearch::Configuration::Column do
|
|
10
10
|
|
11
11
|
it "returns the fully-qualified table and column name" do
|
12
12
|
column = described_class.new("name", nil, Model)
|
13
|
-
column.full_name.
|
13
|
+
expect(column.full_name).to eq(%Q{#{Model.quoted_table_name}."name"})
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
@@ -23,7 +23,7 @@ describe PgSearch::Configuration::Column do
|
|
23
23
|
|
24
24
|
it "returns an expression that casts the column to text and coalesces it with an empty string" do
|
25
25
|
column = described_class.new("name", nil, Model)
|
26
|
-
column.to_sql.
|
26
|
+
expect(column.to_sql).to eq(%Q{coalesce(#{Model.quoted_table_name}."name"::text, '')})
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|