pg_search 2.3.6 → 2.3.8

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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +47 -35
  3. data/.github/workflows/codeql.yml +87 -0
  4. data/.standard.yml +6 -0
  5. data/CHANGELOG.md +23 -0
  6. data/Gemfile +21 -6
  7. data/LICENSE +1 -1
  8. data/README.md +133 -114
  9. data/Rakefile +4 -13
  10. data/lib/pg_search/configuration/column.rb +6 -4
  11. data/lib/pg_search/configuration/foreign_column.rb +1 -1
  12. data/lib/pg_search/configuration.rb +11 -27
  13. data/lib/pg_search/document.rb +8 -8
  14. data/lib/pg_search/features/dmetaphone.rb +1 -1
  15. data/lib/pg_search/features/trigram.rb +4 -4
  16. data/lib/pg_search/features/tsearch.rb +23 -30
  17. data/lib/pg_search/migration/dmetaphone_generator.rb +2 -2
  18. data/lib/pg_search/migration/generator.rb +5 -5
  19. data/lib/pg_search/migration/multisearch_generator.rb +2 -2
  20. data/lib/pg_search/model.rb +12 -14
  21. data/lib/pg_search/multisearch/rebuilder.rb +4 -3
  22. data/lib/pg_search/multisearch.rb +4 -2
  23. data/lib/pg_search/multisearchable.rb +7 -7
  24. data/lib/pg_search/normalizer.rb +17 -7
  25. data/lib/pg_search/scope_options.rb +36 -8
  26. data/lib/pg_search/tasks.rb +2 -2
  27. data/lib/pg_search/version.rb +1 -1
  28. data/lib/pg_search.rb +3 -3
  29. data/pg_search.gemspec +16 -31
  30. data/spec/integration/associations_spec.rb +118 -106
  31. data/spec/integration/deprecation_spec.rb +12 -9
  32. data/spec/integration/pagination_spec.rb +1 -0
  33. data/spec/integration/pg_search_spec.rb +343 -298
  34. data/spec/integration/single_table_inheritance_spec.rb +7 -5
  35. data/spec/lib/pg_search/configuration/association_spec.rb +17 -15
  36. data/spec/lib/pg_search/configuration/column_spec.rb +13 -1
  37. data/spec/lib/pg_search/configuration/foreign_column_spec.rb +5 -4
  38. data/spec/lib/pg_search/features/dmetaphone_spec.rb +4 -4
  39. data/spec/lib/pg_search/features/trigram_spec.rb +32 -33
  40. data/spec/lib/pg_search/features/tsearch_spec.rb +57 -39
  41. data/spec/lib/pg_search/multisearch/rebuilder_spec.rb +70 -20
  42. data/spec/lib/pg_search/multisearch_spec.rb +8 -8
  43. data/spec/lib/pg_search/multisearchable_spec.rb +34 -26
  44. data/spec/lib/pg_search/normalizer_spec.rb +11 -11
  45. data/spec/lib/pg_search_spec.rb +22 -18
  46. data/spec/spec_helper.rb +3 -18
  47. data/spec/support/database.rb +6 -6
  48. metadata +11 -219
  49. data/.codeclimate.yml +0 -17
  50. data/.rubocop.yml +0 -137
  51. data/.travis.yml +0 -37
  52. data/spec/.rubocop.yml +0 -14
  53. data/spec/integration/.rubocop.yml +0 -11
data/README.md CHANGED
@@ -13,10 +13,10 @@ Read the blog post introducing PgSearch at https://tanzu.vmware.com/content/blog
13
13
 
14
14
  ## REQUIREMENTS
15
15
 
16
- * Ruby 2.6+
17
- * ActiveRecord 5.2+
18
- * PostgreSQL 9.2+
19
- * [PostgreSQL extensions](https://github.com/Casecommons/pg_search/wiki/Installing-PostgreSQL-Extensions) for certain features
16
+ - Ruby 3.3+
17
+ - Active Record 7.2+
18
+ - PostgreSQL 9.2+
19
+ - [PostgreSQL extensions](https://github.com/Casecommons/pg_search/wiki/Installing-PostgreSQL-Extensions) for certain features
20
20
 
21
21
  ## INSTALL
22
22
 
@@ -48,48 +48,49 @@ To add PgSearch to an Active Record model, simply include the PgSearch module.
48
48
  class Shape < ActiveRecord::Base
49
49
  include PgSearch::Model
50
50
  end
51
- ```
51
+ ```
52
52
 
53
53
  ### Contents
54
- * [Multi-search vs. search scopes](#multi-search-vs-search-scopes)
55
- * [Multi-search](#multi-search)
56
- * [Setup](#setup)
57
- * [`multisearchable`](#multisearchable)
58
- * [More Options ](#more-options)
59
- * [Multi-search associations](#multi-search-associations)
60
- * [Searching in the global search index](#searching-in-the-global-search-index)
61
- * [Chaining method calls onto the results](#chaining-method-calls-onto-the-results)
62
- * [Configuring multi-search](#configuring-multi-search)
63
- * [Rebuilding search documents for a given class](#rebuilding-search-documents-for-a-given-class)
64
- * [Disabling multi-search indexing temporarily](#disabling-multi-search-indexing-temporarily)
65
- * [`pg_search_scope`](#pg_search_scope)
66
- * [Searching against one column](#searching-against-one-column)
67
- * [Searching against multiple columns](#searching-against-multiple-columns)
68
- * [Dynamic search scopes](#dynamic-search-scopes)
69
- * [Searching through associations](#searching-through-associations)
70
- * [Searching using different search features](#searching-using-different-search-features)
71
- * [`:tsearch` (Full Text Search)](#tsearch-full-text-search)
72
- * [Weighting](#weighting)
73
- * [`:prefix` (PostgreSQL 8.4 and newer only)](#prefix-postgresql-84-and-newer-only)
74
- * [`:negation`](#negation)
75
- * [`:dictionary`](#dictionary)
76
- * [`:normalization`](#normalization)
77
- * [`:any_word`](#any_word)
78
- * [`:sort_only`](#sort_only)
79
- * [`:highlight`](#highlight)
80
- * [`:dmetaphone` (Double Metaphone soundalike search)](#dmetaphone-double-metaphone-soundalike-search)
81
- * [`:trigram` (Trigram search)](#trigram-trigram-search)
82
- * [`:threshold`](#threshold)
83
- * [`:word_similarity`](#word_similarity)
84
- * [Limiting Fields When Combining Features](#limiting-fields-when-combining-features)
85
- * [Ignoring accent marks](#ignoring-accent-marks)
86
- * [Using tsvector columns](#using-tsvector-columns)
87
- * [Combining multiple tsvectors](#combining-multiple-tsvectors)
88
- * [Configuring ranking and ordering](#configuring-ranking-and-ordering)
89
- * [`:ranked_by` (Choosing a ranking algorithm)](#ranked_by-choosing-a-ranking-algorithm)
90
- * [`:order_within_rank` (Breaking ties)](#order_within_rank-breaking-ties)
91
- * [`PgSearch#pg_search_rank` (Reading a record's rank as a Float)](#pgsearchpg_search_rank-reading-a-records-rank-as-a-float)
92
- * [Search rank and chained scopes](#search-rank-and-chained-scopes)
54
+
55
+ - [Multi-search vs. search scopes](#multi-search-vs-search-scopes)
56
+ - [Multi-search](#multi-search)
57
+ - [Setup](#setup)
58
+ - [`multisearchable`](#multisearchable)
59
+ - [More Options ](#more-options)
60
+ - [Multi-search associations](#multi-search-associations)
61
+ - [Searching in the global search index](#searching-in-the-global-search-index)
62
+ - [Chaining method calls onto the results](#chaining-method-calls-onto-the-results)
63
+ - [Configuring multi-search](#configuring-multi-search)
64
+ - [Rebuilding search documents for a given class](#rebuilding-search-documents-for-a-given-class)
65
+ - [Disabling multi-search indexing temporarily](#disabling-multi-search-indexing-temporarily)
66
+ - [`pg_search_scope`](#pg_search_scope)
67
+ - [Searching against one column](#searching-against-one-column)
68
+ - [Searching against multiple columns](#searching-against-multiple-columns)
69
+ - [Dynamic search scopes](#dynamic-search-scopes)
70
+ - [Searching through associations](#searching-through-associations)
71
+ - [Searching using different search features](#searching-using-different-search-features)
72
+ - [`:tsearch` (Full Text Search)](#tsearch-full-text-search)
73
+ - [Weighting](#weighting)
74
+ - [`:prefix` (PostgreSQL 8.4 and newer only)](#prefix-postgresql-84-and-newer-only)
75
+ - [`:negation`](#negation)
76
+ - [`:dictionary`](#dictionary)
77
+ - [`:normalization`](#normalization)
78
+ - [`:any_word`](#any_word)
79
+ - [`:sort_only`](#sort_only)
80
+ - [`:highlight`](#highlight)
81
+ - [`:dmetaphone` (Double Metaphone soundalike search)](#dmetaphone-double-metaphone-soundalike-search)
82
+ - [`:trigram` (Trigram search)](#trigram-trigram-search)
83
+ - [`:threshold`](#threshold)
84
+ - [`:word_similarity`](#word_similarity)
85
+ - [Limiting Fields When Combining Features](#limiting-fields-when-combining-features)
86
+ - [Ignoring accent marks](#ignoring-accent-marks)
87
+ - [Using tsvector columns](#using-tsvector-columns)
88
+ - [Combining multiple tsvectors](#combining-multiple-tsvectors)
89
+ - [Configuring ranking and ordering](#configuring-ranking-and-ordering)
90
+ - [`:ranked_by` (Choosing a ranking algorithm)](#ranked_by-choosing-a-ranking-algorithm)
91
+ - [`:order_within_rank` (Breaking ties)](#order_within_rank-breaking-ties)
92
+ - [`PgSearch#pg_search_rank` (Reading a record's rank as a Float)](#pgsearchpg_search_rank-reading-a-records-rank-as-a-float)
93
+ - [Search rank and chained scopes](#search-rank-and-chained-scopes)
93
94
 
94
95
  ### Multi-search vs. search scopes
95
96
 
@@ -198,17 +199,22 @@ problematic_record.published? # => true
198
199
  PgSearch.multisearch("timestamp") # => Includes problematic_record
199
200
  ```
200
201
 
201
- #### More Options
202
+ #### More Options
202
203
 
203
204
  **Conditionally update pg_search_documents**
204
205
 
205
- You can specify an `:update_if` parameter to conditionally update pg_search documents. For example:
206
+ You can also use the `:update_if` option to pass a Proc or method name to call
207
+ to determine whether or not a particular record should be updated.
208
+
209
+ Note that the Proc or method name is called in an `after_save` hook, so if you
210
+ are relying on ActiveRecord dirty flags use `*_previously_changed?`.
206
211
 
207
212
  ```ruby
208
- multisearchable(
209
- against: [:body],
210
- update_if: :body_changed?
211
- )
213
+ class Message < ActiveRecord::Base
214
+ include PgSearch::Model
215
+ multisearchable against: [:body],
216
+ update_if: :body_previously_changed?
217
+ end
212
218
  ```
213
219
 
214
220
  **Specify additional attributes to be saved on the pg_search_documents table**
@@ -241,7 +247,8 @@ This allows much faster searches without joins later on by doing something like:
241
247
  PgSearch.multisearch(params['search']).where(author_id: 2)
242
248
  ```
243
249
 
244
- *NOTE: You must currently manually call `record.update_pg_search_document` for the additional attribute to be included in the pg_search_documents table*
250
+ _NOTE: You must currently manually call `record.update_pg_search_document` for
251
+ the additional attribute to be included in the pg_search_documents table_
245
252
 
246
253
  #### Multi-search associations
247
254
 
@@ -325,18 +332,18 @@ To regenerate the documents for a given class, run:
325
332
  PgSearch::Multisearch.rebuild(Product)
326
333
  ```
327
334
 
328
- The ```rebuild``` method will delete all the documents for the given class
335
+ The `rebuild` method will delete all the documents for the given class
329
336
  before regenerating them. In some situations this may not be desirable,
330
- such as when you're using single-table inheritance and ```searchable_type```
331
- is your base class. You can prevent ```rebuild``` from deleting your records
337
+ such as when you're using single-table inheritance and `searchable_type`
338
+ is your base class. You can prevent `rebuild` from deleting your records
332
339
  like so:
333
340
 
334
341
  ```ruby
335
342
  PgSearch::Multisearch.rebuild(Product, clean_up: false)
336
343
  ```
337
344
 
338
- ```rebuild``` runs inside a single transaction. To run outside of a transaction,
339
- you can pass ```transactional: false``` like so:
345
+ `rebuild` runs inside a single transaction. To run outside of a transaction,
346
+ you can pass `transactional: false` like so:
340
347
 
341
348
  ```ruby
342
349
  PgSearch::Multisearch.rebuild(Product, transactional: false)
@@ -353,15 +360,11 @@ pg_search_documents tables. The following will set the schema search path to
353
360
 
354
361
  $ rake pg_search:multisearch:rebuild[BlogPost,my_schema]
355
362
 
356
- For models that are multisearchable :against methods that directly map to
363
+ For models that are multisearchable `:against` methods that directly map to
357
364
  Active Record attributes, an efficient single SQL statement is run to update
358
- the pg_search_documents table all at once. However, if you call any dynamic
359
- methods in :against, the following strategy will be used:
360
-
361
- ```ruby
362
- PgSearch::Document.delete_all(searchable_type: "Ingredient")
363
- Ingredient.find_each { |record| record.update_pg_search_document }
364
- ```
365
+ the `pg_search_documents` table all at once. However, if you call any dynamic
366
+ methods in `:against` then `update_pg_search_document` will be called on the
367
+ individual records being indexed in batches.
365
368
 
366
369
  You can also provide a custom implementation for rebuilding the documents by
367
370
  adding a class method called `rebuild_pg_search_documents` to your model.
@@ -397,7 +400,8 @@ class Movie < ActiveRecord::Base
397
400
  end
398
401
  end
399
402
  ```
400
- **Note:** If using PostgreSQL before 9.1, replace the `CONCAT_WS()` function call with double-pipe concatenation, eg. `(movies.name || ' ' || directors.name)`. However, now be aware that if *any* of the joined values is NULL then the final `content` value will also be NULL, whereas `CONCAT_WS()` will selectively ignore NULL values.
403
+
404
+ **Note:** If using PostgreSQL before 9.1, replace the `CONCAT_WS()` function call with double-pipe concatenation, eg. `(movies.name || ' ' || directors.name)`. However, now be aware that if _any_ of the joined values is NULL then the final `content` value will also be NULL, whereas `CONCAT_WS()` will selectively ignore NULL values.
401
405
 
402
406
  #### Disabling multi-search indexing temporarily
403
407
 
@@ -550,13 +554,27 @@ class Beer < ActiveRecord::Base
550
554
  end
551
555
  ```
552
556
 
553
- The currently implemented features are
557
+ Here's an example if you pass multiple :using options with additional configurations.
558
+
559
+ ```ruby
560
+ class Beer < ActiveRecord::Base
561
+ include PgSearch::Model
562
+ pg_search_scope :search_name,
563
+ against: :name,
564
+ using: {
565
+ :trigram => {},
566
+ :dmetaphone => {},
567
+ :tsearch => { :prefix => true }
568
+ }
569
+ end
570
+ ```
554
571
 
555
- * :tsearch - [Full text search](http://www.postgresql.org/docs/current/static/textsearch-intro.html), which is built-in to PostgreSQL
556
- * :trigram - [Trigram search](http://www.postgresql.org/docs/current/static/pgtrgm.html), which
557
- requires the trigram extension
558
- * :dmetaphone - [Double Metaphone search](http://www.postgresql.org/docs/current/static/fuzzystrmatch.html#AEN177521), which requires the fuzzystrmatch extension
572
+ The currently implemented features are
559
573
 
574
+ - :tsearch - [Full text search](http://www.postgresql.org/docs/current/static/textsearch-intro.html), which is built-in to PostgreSQL
575
+ - :trigram - [Trigram search](http://www.postgresql.org/docs/current/static/pgtrgm.html), which
576
+ requires the trigram extension
577
+ - :dmetaphone - [Double Metaphone search](http://www.postgresql.org/docs/current/static/fuzzystrmatch.html#AEN177521), which requires the fuzzystrmatch extension
560
578
 
561
579
  #### :tsearch (Full Text Search)
562
580
 
@@ -564,6 +582,7 @@ PostgreSQL's built-in full text search supports weighting, prefix searches,
564
582
  and stemming in multiple languages.
565
583
 
566
584
  ##### Weighting
585
+
567
586
  Each searchable column can be given a weight of "A", "B", "C", or "D". Columns
568
587
  with earlier letters are weighted higher than those with later letters. So, in
569
588
  the following example, the title is the most important, followed by the
@@ -627,6 +646,7 @@ robin = Superhero.create name: 'Robin'
627
646
 
628
647
  Superhero.whose_name_starts_with("Bat") # => [batman, batgirl]
629
648
  ```
649
+
630
650
  ##### :negation
631
651
 
632
652
  PostgreSQL's full text search matches all search terms by default. If you want
@@ -662,7 +682,7 @@ Animal.with_name_matching("fish !red !blue") # => [one_fish, two_fish]
662
682
 
663
683
  PostgreSQL full text search also support multiple dictionaries for stemming.
664
684
  You can learn more about how dictionaries work by reading the [PostgreSQL
665
- documention](http://www.postgresql.org/docs/current/static/textsearch-dictionaries.html).
685
+ documention](http://www.postgresql.org/docs/current/static/textsearch-dictionaries.html).
666
686
  If you use one of the language dictionaries, such as "english",
667
687
  then variants of words (e.g. "jumping" and "jumped") will match each other. If
668
688
  you don't want stemming, you should pick the "simple" dictionary which does
@@ -684,12 +704,12 @@ class BoringTweet < ActiveRecord::Base
684
704
  }
685
705
  end
686
706
 
687
- sleepy = BoringTweet.create! text: "I snoozed my alarm for fourteen hours today. I bet I can beat that tomorrow! #sleepy"
707
+ sleep = BoringTweet.create! text: "I snoozed my alarm for fourteen hours today. I bet I can beat that tomorrow! #sleep"
688
708
  sleeping = BoringTweet.create! text: "You know what I like? Sleeping. That's what. #enjoyment"
689
- sleeper = BoringTweet.create! text: "Have you seen Woody Allen's movie entitled Sleeper? Me neither. #boycott"
709
+ sleeps = BoringTweet.create! text: "In the jungle, the mighty jungle, the lion sleeps #tonight"
690
710
 
691
- BoringTweet.kinda_matching("sleeping") # => [sleepy, sleeping, sleeper]
692
- BoringTweet.literally_matching("sleeping") # => [sleeping]
711
+ BoringTweet.kinda_matching("sleeping") # => [sleep, sleeping, sleeps]
712
+ BoringTweet.literally_matching("sleeps") # => [sleeps]
693
713
  ```
694
714
 
695
715
  ##### :normalization
@@ -787,7 +807,6 @@ Person.search('ash hines') # => [exact, one_exact_one_close, one_exact]
787
807
  Adding .with_pg_search_highlight after the pg_search_scope you can access to
788
808
  `pg_highlight` attribute for each object.
789
809
 
790
-
791
810
  ```ruby
792
811
  class Person < ActiveRecord::Base
793
812
  include PgSearch::Model
@@ -798,8 +817,8 @@ class Person < ActiveRecord::Base
798
817
  highlight: {
799
818
  StartSel: '<b>',
800
819
  StopSel: '</b>',
801
- MaxWords: 123,
802
- MinWords: 456,
820
+ MinWords: 123,
821
+ MaxWords: 456,
803
822
  ShortWord: 4,
804
823
  HighlightAll: true,
805
824
  MaxFragments: 3,
@@ -834,7 +853,7 @@ used for searching.
834
853
  Double Metaphone support is currently available as part of the [fuzzystrmatch
835
854
  extension](http://www.postgresql.org/docs/current/static/fuzzystrmatch.html)
836
855
  that must be installed before this feature can be used. In addition to the
837
- extension, you must install a utility function into your database. To generate
856
+ extension, you must install a utility function into your database. To generate
838
857
  and run a migration for this, run:
839
858
 
840
859
  $ rails g pg_search:migration:dmetaphone
@@ -869,7 +888,7 @@ Trigram search works by counting how many three-letter substrings (or
869
888
  Trigram search has some ability to work even with typos and misspellings in
870
889
  the query or text.
871
890
 
872
- Trigram support is currently available as part of the
891
+ Trigram support is currently available as part of the
873
892
  [pg_trgm extension](http://www.postgresql.org/docs/current/static/pgtrgm.html) that must be installed before this
874
893
  feature can be used.
875
894
 
@@ -933,7 +952,7 @@ Vegetable.strictly_spelled_like("collyflower") # => []
933
952
  Allows you to match words in longer strings.
934
953
  By default, trigram searches use `%` or `similarity()` as a similarity value.
935
954
  Set `word_similarity` to `true` to opt for `<%` and `word_similarity` instead.
936
- This causes the trigram search to use the similarity of the query term
955
+ This causes the trigram search to use the similarity of the query term
937
956
  and the word with greatest similarity.
938
957
 
939
958
  ```ruby
@@ -959,12 +978,12 @@ Sentence.similarity_like("word") # => []
959
978
  Sentence.word_similarity_like("word") # => [sentence]
960
979
  ```
961
980
 
962
- ### Limiting Fields When Combining Features
981
+ ### Limiting Fields When Combining Features
963
982
 
964
- Sometimes when doing queries combining different features you
965
- might want to searching against only some of the fields with certain features.
983
+ Sometimes when doing queries combining different features you
984
+ might want to search against only some of the fields with certain features.
966
985
  For example perhaps you want to only do a trigram search against the shorter fields
967
- so that you don't need to reduce the threshold excessively. You can specify
986
+ so that you don't need to reduce the threshold excessively. You can specify
968
987
  which fields using the 'only' option:
969
988
 
970
989
  ```ruby
@@ -983,7 +1002,7 @@ class Image < ActiveRecord::Base
983
1002
  end
984
1003
  ```
985
1004
 
986
- Now you can succesfully retrieve an Image with a file_name: 'image_foo.jpg'
1005
+ Now you can succesfully retrieve an Image with a file_name: 'image_foo.jpg'
987
1006
  and long_description: 'This description is so long that it would make a trigram search
988
1007
  fail any reasonable threshold limit' with:
989
1008
 
@@ -1036,31 +1055,31 @@ as it offloads creation of the tsvector that the tsquery is evaluated against.
1036
1055
 
1037
1056
  To use this functionality you'll need to do a few things:
1038
1057
 
1039
- * Create a column of type tsvector that you'd like to search against. If you
1040
- want to search using multiple search methods, for example tsearch and
1041
- dmetaphone, you'll need a column for each.
1042
- * Create a trigger function that will update the column(s) using the
1043
- expression appropriate for that type of search. See:
1044
- [the PostgreSQL documentation for text search triggers](http://www.postgresql.org/docs/current/static/textsearch-features.html#TEXTSEARCH-UPDATE-TRIGGERS)
1045
- * Should you have any pre-existing data in the table, update the
1046
- newly-created tsvector columns with the expression that your trigger
1047
- function uses.
1048
- * Add the option to pg_search_scope, e.g:
1049
-
1050
- ```ruby
1051
- pg_search_scope :fast_content_search,
1052
- against: :content,
1053
- using: {
1054
- dmetaphone: {
1055
- tsvector_column: 'tsvector_content_dmetaphone'
1056
- },
1057
- tsearch: {
1058
- dictionary: 'english',
1059
- tsvector_column: 'tsvector_content_tsearch'
1060
- },
1061
- trigram: {} # trigram does not use tsvectors
1062
- }
1063
- ```
1058
+ - Create a column of type tsvector that you'd like to search against. If you
1059
+ want to search using multiple search methods, for example tsearch and
1060
+ dmetaphone, you'll need a column for each.
1061
+ - Create a trigger function that will update the column(s) using the
1062
+ expression appropriate for that type of search. See:
1063
+ [the PostgreSQL documentation for text search triggers](http://www.postgresql.org/docs/current/static/textsearch-features.html#TEXTSEARCH-UPDATE-TRIGGERS)
1064
+ - Should you have any pre-existing data in the table, update the
1065
+ newly-created tsvector columns with the expression that your trigger
1066
+ function uses.
1067
+ - Add the option to pg_search_scope, e.g:
1068
+
1069
+ ```ruby
1070
+ pg_search_scope :fast_content_search,
1071
+ against: :content,
1072
+ using: {
1073
+ dmetaphone: {
1074
+ tsvector_column: 'tsvector_content_dmetaphone'
1075
+ },
1076
+ tsearch: {
1077
+ dictionary: 'english',
1078
+ tsvector_column: 'tsvector_content_tsearch'
1079
+ },
1080
+ trigram: {} # trigram does not use tsvectors
1081
+ }
1082
+ ```
1064
1083
 
1065
1084
  Please note that the :against column is only used when the tsvector_column is
1066
1085
  not present for the search type.
@@ -1173,9 +1192,9 @@ shirt_brands[1].pg_search_rank #=> 0.0607927
1173
1192
 
1174
1193
  #### Search rank and chained scopes
1175
1194
 
1176
- Each PgSearch scope generates a named subquery for the search rank. If you
1195
+ Each PgSearch scope generates a named subquery for the search rank. If you
1177
1196
  chain multiple scopes then PgSearch will generate a ranking query for each
1178
- scope, so the ranking queries must have unique names. If you need to reference
1197
+ scope, so the ranking queries must have unique names. If you need to reference
1179
1198
  the ranking query (e.g. in a GROUP BY clause) you can regenerate the subquery
1180
1199
  name with the `PgScope::Configuration.alias` method by passing the name of the
1181
1200
  queried table.
@@ -1201,5 +1220,5 @@ for discussing pg_search and other Casebook PBC open source projects.
1201
1220
 
1202
1221
  ## LICENSE
1203
1222
 
1204
- Copyright © 2010–2021 [Casebook PBC](http://www.casebook.net).
1223
+ Copyright © 2010–2022 [Casebook PBC](http://www.casebook.net).
1205
1224
  Licensed under the MIT license, see [LICENSE](/LICENSE) file.
data/Rakefile CHANGED
@@ -1,20 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'bundler'
3
+ require "bundler"
4
4
  Bundler::GemHelper.install_tasks
5
5
 
6
- require 'rspec/core/rake_task'
6
+ require "rspec/core/rake_task"
7
7
  RSpec::Core::RakeTask.new(:spec)
8
8
 
9
- require "rubocop/rake_task"
10
- RuboCop::RakeTask.new do |t|
11
- t.options = %w[--display-cop-names]
12
- end
9
+ require "standard/rake"
13
10
 
14
- desc "Check test coverage"
15
- task :undercover do
16
- system("git fetch --unshallow") if ENV["CI"]
17
- exit(1) unless system("bin/undercover --compare origin/master")
18
- end
19
-
20
- task default: %w[spec rubocop undercover]
11
+ task default: %w[spec standard]
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'digest'
3
+ require "digest"
4
4
 
5
5
  module PgSearch
6
6
  class Configuration
@@ -9,18 +9,20 @@ module PgSearch
9
9
 
10
10
  def initialize(column_name, weight, model)
11
11
  @name = column_name.to_s
12
- @column_name = column_name.to_s
12
+ @column_name = column_name
13
13
  @weight = weight
14
14
  @model = model
15
15
  @connection = model.connection
16
16
  end
17
17
 
18
18
  def full_name
19
+ return @column_name if @column_name.is_a?(Arel::Nodes::SqlLiteral)
20
+
19
21
  "#{table_name}.#{column_name}"
20
22
  end
21
23
 
22
24
  def to_sql
23
- "coalesce(#{expression}::text, '')"
25
+ "coalesce((#{expression})::text, '')"
24
26
  end
25
27
 
26
28
  private
@@ -30,7 +32,7 @@ module PgSearch
30
32
  end
31
33
 
32
34
  def column_name
33
- @connection.quote_column_name(@column_name)
35
+ @connection.quote_column_name(@name)
34
36
  end
35
37
 
36
38
  def expression
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'digest'
3
+ require "digest"
4
4
 
5
5
  module PgSearch
6
6
  class Configuration
@@ -23,9 +23,7 @@ module PgSearch
23
23
  end
24
24
  end
25
25
 
26
- def columns
27
- regular_columns + associated_columns
28
- end
26
+ def columns = regular_columns + associated_columns
29
27
 
30
28
  def regular_columns
31
29
  return [] unless options[:against]
@@ -43,46 +41,31 @@ module PgSearch
43
41
  end.flatten
44
42
  end
45
43
 
46
- def associated_columns
47
- associations.map(&:columns).flatten
48
- end
44
+ def associated_columns = associations.map(&:columns).flatten
49
45
 
50
- def query
51
- options[:query].to_s
52
- end
46
+ def query = options[:query].to_s
53
47
 
54
- def ignore
55
- Array(options[:ignoring])
56
- end
48
+ def ignore = Array(options[:ignoring])
57
49
 
58
- def ranking_sql
59
- options[:ranked_by]
60
- end
50
+ def ranking_sql = options[:ranked_by]
61
51
 
62
- def features
63
- Array(options[:using])
64
- end
52
+ def features = Array(options[:using])
65
53
 
66
54
  def feature_options
67
- @feature_options ||= {}.tap do |hash|
68
- features.map do |feature_name, feature_options|
69
- hash[feature_name] = feature_options
70
- end
71
- end
55
+ @feature_options ||= features.to_h { |name, opts| [name, opts] }
72
56
  end
73
57
 
74
- def order_within_rank
75
- options[:order_within_rank]
76
- end
58
+ def order_within_rank = options[:order_within_rank]
77
59
 
78
60
  private
79
61
 
80
62
  attr_reader :options
81
63
 
82
64
  def default_options
83
- { using: :tsearch }
65
+ {using: :tsearch}
84
66
  end
85
67
 
68
+ # standard:disable Lint/UselessConstantScoping
86
69
  VALID_KEYS = %w[
87
70
  against ranked_by ignoring using query associated_against order_within_rank
88
71
  ].map(&:to_sym)
@@ -90,6 +73,7 @@ module PgSearch
90
73
  VALID_VALUES = {
91
74
  ignoring: [:accents]
92
75
  }.freeze
76
+ # standard:enable Lint/UselessConstantScoping
93
77
 
94
78
  def assert_valid_options(options)
95
79
  unless options[:against] || options[:associated_against] || using_tsvector_column?(options[:using])
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'logger'
3
+ require "logger"
4
4
 
5
5
  module PgSearch
6
- class Document < ActiveRecord::Base
6
+ class Document < ActiveRecord::Base # standard:disable Rails/ApplicationRecord
7
7
  include PgSearch::Model
8
8
 
9
- self.table_name = 'pg_search_documents'
9
+ self.table_name = "pg_search_documents"
10
10
  belongs_to :searchable, polymorphic: true
11
11
 
12
12
  # The logger might not have loaded yet.
@@ -17,12 +17,12 @@ module PgSearch
17
17
 
18
18
  pg_search_scope :search, lambda { |*args|
19
19
  options = if PgSearch.multisearch_options.respond_to?(:call)
20
- PgSearch.multisearch_options.call(*args)
21
- else
22
- { query: args.first }.merge(PgSearch.multisearch_options)
23
- end
20
+ PgSearch.multisearch_options.call(*args)
21
+ else
22
+ {query: args.first}.merge(PgSearch.multisearch_options)
23
+ end
24
24
 
25
- { against: :content }.merge(options)
25
+ {against: :content}.merge(options)
26
26
  }
27
27
  end
28
28
  end
@@ -7,7 +7,7 @@ module PgSearch
7
7
  class DMetaphone
8
8
  def initialize(query, options, columns, model, normalizer)
9
9
  dmetaphone_normalizer = Normalizer.new(normalizer)
10
- options = (options || {}).merge(dictionary: 'simple')
10
+ options = (options || {}).merge(dictionary: "simple")
11
11
  @tsearch = TSearch.new(query, options, columns, model, dmetaphone_normalizer)
12
12
  end
13
13
 
@@ -35,17 +35,17 @@ module PgSearch
35
35
 
36
36
  def similarity_function
37
37
  if word_similarity?
38
- 'word_similarity'
38
+ "word_similarity"
39
39
  else
40
- 'similarity'
40
+ "similarity"
41
41
  end
42
42
  end
43
43
 
44
44
  def infix_operator
45
45
  if word_similarity?
46
- '<%'
46
+ "<%"
47
47
  else
48
- '%'
48
+ "%"
49
49
  end
50
50
  end
51
51