pg_search 2.1.2 → 2.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.codeclimate.yml +1 -0
- data/.editorconfig +10 -0
- data/.github/dependabot.yml +11 -0
- data/.github/workflows/ci.yml +75 -0
- data/.jrubyrc +1 -0
- data/.rubocop.yml +95 -10
- data/.travis.yml +26 -48
- data/CHANGELOG.md +179 -112
- data/CODE_OF_CONDUCT.md +76 -0
- data/CONTRIBUTING.md +5 -3
- data/Gemfile +6 -4
- data/LICENSE +1 -1
- data/README.md +307 -198
- data/Rakefile +7 -3
- data/lib/pg_search/configuration/association.rb +2 -0
- data/lib/pg_search/configuration/column.rb +2 -0
- data/lib/pg_search/configuration/foreign_column.rb +2 -0
- data/lib/pg_search/configuration.rb +20 -6
- data/lib/pg_search/document.rb +7 -5
- data/lib/pg_search/features/dmetaphone.rb +7 -7
- data/lib/pg_search/features/feature.rb +4 -2
- data/lib/pg_search/features/trigram.rb +31 -5
- data/lib/pg_search/features/tsearch.rb +18 -14
- data/lib/pg_search/features.rb +2 -0
- data/lib/pg_search/migration/dmetaphone_generator.rb +3 -1
- data/lib/pg_search/migration/generator.rb +4 -2
- data/lib/pg_search/migration/multisearch_generator.rb +2 -1
- data/lib/pg_search/migration/templates/add_pg_search_dmetaphone_support_functions.rb.erb +6 -6
- data/lib/pg_search/migration/templates/create_pg_search_documents.rb.erb +3 -3
- data/lib/pg_search/model.rb +57 -0
- data/lib/pg_search/multisearch/rebuilder.rb +14 -6
- data/lib/pg_search/multisearch.rb +23 -6
- data/lib/pg_search/multisearchable.rb +10 -6
- data/lib/pg_search/normalizer.rb +2 -0
- data/lib/pg_search/railtie.rb +2 -0
- data/lib/pg_search/scope_options.rb +26 -49
- data/lib/pg_search/tasks.rb +5 -1
- data/lib/pg_search/version.rb +3 -1
- data/lib/pg_search.rb +17 -55
- data/pg_search.gemspec +19 -11
- data/spec/.rubocop.yml +2 -2
- data/spec/integration/.rubocop.yml +11 -0
- data/spec/integration/associations_spec.rb +125 -162
- data/spec/integration/deprecation_spec.rb +33 -0
- data/spec/integration/pagination_spec.rb +10 -8
- data/spec/integration/pg_search_spec.rb +359 -306
- data/spec/integration/single_table_inheritance_spec.rb +18 -17
- data/spec/lib/pg_search/configuration/association_spec.rb +17 -13
- data/spec/lib/pg_search/configuration/column_spec.rb +2 -0
- data/spec/lib/pg_search/configuration/foreign_column_spec.rb +6 -4
- data/spec/lib/pg_search/features/dmetaphone_spec.rb +6 -4
- data/spec/lib/pg_search/features/trigram_spec.rb +51 -20
- data/spec/lib/pg_search/features/tsearch_spec.rb +29 -21
- data/spec/lib/pg_search/multisearch/rebuilder_spec.rb +151 -85
- data/spec/lib/pg_search/multisearch_spec.rb +67 -37
- data/spec/lib/pg_search/multisearchable_spec.rb +217 -123
- data/spec/lib/pg_search/normalizer_spec.rb +14 -10
- data/spec/lib/pg_search_spec.rb +102 -89
- data/spec/spec_helper.rb +25 -6
- data/spec/support/database.rb +19 -21
- data/spec/support/with_model.rb +2 -0
- metadata +106 -29
- data/.autotest +0 -5
- data/.rubocop_todo.yml +0 -163
- data/Guardfile +0 -6
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/module/delegation"
|
2
4
|
|
3
5
|
module PgSearch
|
@@ -12,23 +14,15 @@ module PgSearch
|
|
12
14
|
|
13
15
|
def apply(scope)
|
14
16
|
scope = include_table_aliasing_for_rank(scope)
|
15
|
-
rank_table_alias = scope.pg_search_rank_table_alias(:
|
17
|
+
rank_table_alias = scope.pg_search_rank_table_alias(include_counter: true)
|
16
18
|
|
17
19
|
scope
|
18
20
|
.joins(rank_join(rank_table_alias))
|
19
21
|
.order(Arel.sql("#{rank_table_alias}.rank DESC, #{order_within_rank}"))
|
20
|
-
.extend(DisableEagerLoading)
|
21
22
|
.extend(WithPgSearchRank)
|
22
23
|
.extend(WithPgSearchHighlight[feature_for(:tsearch)])
|
23
24
|
end
|
24
25
|
|
25
|
-
# workaround for https://github.com/Casecommons/pg_search/issues/14
|
26
|
-
module DisableEagerLoading
|
27
|
-
def eager_loading?
|
28
|
-
return false
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
26
|
module WithPgSearchHighlight
|
33
27
|
def self.[](tsearch)
|
34
28
|
Module.new do
|
@@ -38,16 +32,13 @@ module PgSearch
|
|
38
32
|
end
|
39
33
|
|
40
34
|
def tsearch
|
41
|
-
raise TypeError
|
35
|
+
raise TypeError, "You need to instantiate this module with []"
|
42
36
|
end
|
43
37
|
|
44
38
|
def with_pg_search_highlight
|
45
39
|
scope = self
|
46
|
-
scope.select(
|
47
|
-
|
48
|
-
|
49
|
-
def pg_search_highlight_field
|
50
|
-
"(#{highlight}) AS pg_search_highlight, #{table_name}.*"
|
40
|
+
scope = scope.select("#{table_name}.*") unless scope.select_values.any?
|
41
|
+
scope.select("(#{highlight}) AS pg_search_highlight")
|
51
42
|
end
|
52
43
|
|
53
44
|
def highlight
|
@@ -64,10 +55,10 @@ module PgSearch
|
|
64
55
|
end
|
65
56
|
|
66
57
|
module PgSearchRankTableAliasing
|
67
|
-
def pg_search_rank_table_alias(include_counter
|
58
|
+
def pg_search_rank_table_alias(include_counter: false)
|
68
59
|
components = [arel_table.name]
|
69
60
|
if include_counter
|
70
|
-
count =
|
61
|
+
count = increment_counter
|
71
62
|
components << count if count > 0
|
72
63
|
end
|
73
64
|
|
@@ -76,22 +67,16 @@ module PgSearch
|
|
76
67
|
|
77
68
|
private
|
78
69
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
@
|
83
|
-
end
|
84
|
-
|
85
|
-
def pg_search_scope_application_count_plus_plus
|
86
|
-
count = pg_search_scope_application_count
|
87
|
-
self.pg_search_scope_application_count = pg_search_scope_application_count + 1
|
88
|
-
count
|
70
|
+
def increment_counter
|
71
|
+
@counter ||= 0
|
72
|
+
ensure
|
73
|
+
@counter += 1
|
89
74
|
end
|
90
75
|
end
|
91
76
|
|
92
77
|
private
|
93
78
|
|
94
|
-
delegate :connection, :quoted_table_name, :
|
79
|
+
delegate :connection, :quoted_table_name, to: :model
|
95
80
|
|
96
81
|
def subquery
|
97
82
|
model
|
@@ -105,19 +90,10 @@ module PgSearch
|
|
105
90
|
end
|
106
91
|
|
107
92
|
def conditions
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
conditions.map! do |feature_name, _feature_options|
|
113
|
-
feature_for(feature_name).conditions
|
114
|
-
end
|
115
|
-
|
116
|
-
conditions = conditions.inject do |accumulator, expression|
|
117
|
-
Arel::Nodes::Or.new(accumulator, expression)
|
118
|
-
end
|
119
|
-
|
120
|
-
conditions.to_sql
|
93
|
+
config.features
|
94
|
+
.reject { |_feature_name, feature_options| feature_options && feature_options[:sort_only] }
|
95
|
+
.map { |feature_name, _feature_options| feature_for(feature_name).conditions }
|
96
|
+
.inject { |accumulator, expression| Arel::Nodes::Or.new(accumulator, expression) }
|
121
97
|
end
|
122
98
|
|
123
99
|
def order_within_rank
|
@@ -137,16 +113,16 @@ module PgSearch
|
|
137
113
|
end
|
138
114
|
|
139
115
|
FEATURE_CLASSES = {
|
140
|
-
:
|
141
|
-
:
|
142
|
-
:
|
143
|
-
}
|
116
|
+
dmetaphone: Features::DMetaphone,
|
117
|
+
tsearch: Features::TSearch,
|
118
|
+
trigram: Features::Trigram
|
119
|
+
}.freeze
|
144
120
|
|
145
|
-
def feature_for(feature_name)
|
121
|
+
def feature_for(feature_name)
|
146
122
|
feature_name = feature_name.to_sym
|
147
123
|
feature_class = FEATURE_CLASSES[feature_name]
|
148
124
|
|
149
|
-
raise ArgumentError
|
125
|
+
raise ArgumentError, "Unknown feature: #{feature_name}" unless feature_class
|
150
126
|
|
151
127
|
normalizer = Normalizer.new(config)
|
152
128
|
|
@@ -161,7 +137,7 @@ module PgSearch
|
|
161
137
|
|
162
138
|
def rank
|
163
139
|
(config.ranking_sql || ":tsearch").gsub(/:(\w*)/) do
|
164
|
-
feature_for(
|
140
|
+
feature_for(Regexp.last_match(1)).rank.to_sql
|
165
141
|
end
|
166
142
|
end
|
167
143
|
|
@@ -171,8 +147,9 @@ module PgSearch
|
|
171
147
|
|
172
148
|
def include_table_aliasing_for_rank(scope)
|
173
149
|
return scope if scope.included_modules.include?(PgSearchRankTableAliasing)
|
150
|
+
|
174
151
|
scope.all.spawn.tap do |new_scope|
|
175
|
-
new_scope.
|
152
|
+
new_scope.instance_eval { extend PgSearchRankTableAliasing }
|
176
153
|
end
|
177
154
|
end
|
178
155
|
end
|
data/lib/pg_search/tasks.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'rake'
|
2
4
|
require 'pg_search'
|
3
5
|
|
@@ -5,10 +7,12 @@ namespace :pg_search do
|
|
5
7
|
namespace :multisearch do
|
6
8
|
desc "Rebuild PgSearch multisearch records for a given model"
|
7
9
|
task :rebuild, %i[model schema] => :environment do |_task, args|
|
8
|
-
raise ArgumentError,
|
10
|
+
raise ArgumentError, <<~MESSAGE unless args.model
|
11
|
+
|
9
12
|
You must pass a model as an argument.
|
10
13
|
Example: rake pg_search:multisearch:rebuild[BlogPost]
|
11
14
|
MESSAGE
|
15
|
+
|
12
16
|
model_class = args.model.classify.constantize
|
13
17
|
connection = PgSearch::Document.connection
|
14
18
|
original_schema_search_path = connection.schema_search_path
|
data/lib/pg_search/version.rb
CHANGED
data/lib/pg_search.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_record"
|
2
4
|
require "active_support/concern"
|
3
5
|
require "active_support/core_ext/module/attribute_accessors"
|
@@ -5,6 +7,7 @@ require "active_support/core_ext/string/strip"
|
|
5
7
|
|
6
8
|
require "pg_search/configuration"
|
7
9
|
require "pg_search/features"
|
10
|
+
require "pg_search/model"
|
8
11
|
require "pg_search/multisearch"
|
9
12
|
require "pg_search/multisearchable"
|
10
13
|
require "pg_search/normalizer"
|
@@ -12,7 +15,17 @@ require "pg_search/scope_options"
|
|
12
15
|
require "pg_search/version"
|
13
16
|
|
14
17
|
module PgSearch
|
15
|
-
|
18
|
+
autoload :Document, "pg_search/document"
|
19
|
+
|
20
|
+
def self.included(base)
|
21
|
+
ActiveSupport::Deprecation.warn <<~MESSAGE
|
22
|
+
Directly including `PgSearch` into an Active Record model is deprecated and will be removed in pg_search 3.0.
|
23
|
+
|
24
|
+
Please replace `include PgSearch` with `include PgSearch::Model`.
|
25
|
+
MESSAGE
|
26
|
+
|
27
|
+
base.include PgSearch::Model
|
28
|
+
end
|
16
29
|
|
17
30
|
mattr_accessor :multisearch_options
|
18
31
|
self.multisearch_options = {}
|
@@ -20,29 +33,6 @@ module PgSearch
|
|
20
33
|
mattr_accessor :unaccent_function
|
21
34
|
self.unaccent_function = "unaccent"
|
22
35
|
|
23
|
-
module ClassMethods
|
24
|
-
def pg_search_scope(name, options)
|
25
|
-
options_proc = if options.respond_to?(:call)
|
26
|
-
options
|
27
|
-
else
|
28
|
-
raise ArgumentError, "pg_search_scope expects a Hash or Proc" unless options.respond_to?(:merge)
|
29
|
-
->(query) { {:query => query}.merge(options) }
|
30
|
-
end
|
31
|
-
|
32
|
-
define_singleton_method(name) do |*args|
|
33
|
-
config = Configuration.new(options_proc.call(*args), self)
|
34
|
-
scope_options = ScopeOptions.new(config)
|
35
|
-
scope_options.apply(self)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def multisearchable(options = {})
|
40
|
-
include PgSearch::Multisearchable # rubocop:disable Style/MixinUsage
|
41
|
-
class_attribute :pg_search_multisearchable_options
|
42
|
-
self.pg_search_multisearchable_options = options
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
36
|
class << self
|
47
37
|
def multisearch(*args)
|
48
38
|
PgSearch::Document.search(*args)
|
@@ -64,47 +54,19 @@ module PgSearch
|
|
64
54
|
end
|
65
55
|
end
|
66
56
|
|
67
|
-
def method_missing(symbol, *args)
|
68
|
-
case symbol
|
69
|
-
when :pg_search_rank
|
70
|
-
raise PgSearchRankNotSelected.new unless respond_to?(:pg_search_rank)
|
71
|
-
read_attribute(:pg_search_rank).to_f
|
72
|
-
when :pg_search_highlight
|
73
|
-
raise PgSearchHighlightNotSelected.new unless respond_to?(:pg_search_highlight)
|
74
|
-
read_attribute(:pg_search_highlight)
|
75
|
-
else
|
76
|
-
super
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
def respond_to_missing?(symbol, *args)
|
81
|
-
case symbol
|
82
|
-
when :pg_search_rank
|
83
|
-
attributes.key?(:pg_search_rank)
|
84
|
-
when :pg_search_highlight
|
85
|
-
attributes.key?(:pg_search_highlight)
|
86
|
-
else
|
87
|
-
super
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
57
|
class PgSearchRankNotSelected < StandardError
|
92
58
|
def message
|
93
59
|
"You must chain .with_pg_search_rank after the pg_search_scope " \
|
94
|
-
|
60
|
+
"to access the pg_search_rank attribute on returned records"
|
95
61
|
end
|
96
62
|
end
|
97
63
|
|
98
64
|
class PgSearchHighlightNotSelected < StandardError
|
99
65
|
def message
|
100
66
|
"You must chain .with_pg_search_highlight after the pg_search_scope " \
|
101
|
-
|
67
|
+
"to access the pg_search_highlight attribute on returned records"
|
102
68
|
end
|
103
69
|
end
|
104
70
|
end
|
105
71
|
|
106
|
-
|
107
|
-
require "pg_search/document"
|
108
|
-
end
|
109
|
-
|
110
|
-
require "pg_search/railtie" if defined?(Rails)
|
72
|
+
require "pg_search/railtie" if defined?(Rails::Railtie)
|
data/pg_search.gemspec
CHANGED
@@ -1,32 +1,40 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
$LOAD_PATH.push File.expand_path('lib', __dir__)
|
2
4
|
require 'pg_search/version'
|
3
5
|
|
4
|
-
Gem::Specification.new do |s|
|
6
|
+
Gem::Specification.new do |s| # rubocop:disable Metrics/BlockLength
|
5
7
|
s.name = 'pg_search'
|
6
8
|
s.version = PgSearch::VERSION
|
7
9
|
s.platform = Gem::Platform::RUBY
|
8
10
|
s.authors = ['Grant Hutchins', 'Case Commons, LLC']
|
9
11
|
s.email = %w[gems@nertzy.com casecommons-dev@googlegroups.com]
|
10
12
|
s.homepage = 'https://github.com/Casecommons/pg_search'
|
11
|
-
s.summary =
|
12
|
-
s.description =
|
13
|
+
s.summary = "PgSearch builds Active Record named scopes that take advantage of PostgreSQL's full text search"
|
14
|
+
s.description = "PgSearch builds Active Record named scopes that take advantage of PostgreSQL's full text search"
|
13
15
|
s.licenses = ['MIT']
|
16
|
+
s.metadata["rubygems_mfa_required"] = "true"
|
14
17
|
|
15
18
|
s.files = `git ls-files`.split("\n")
|
16
19
|
s.test_files = `git ls-files -- spec/*`.split("\n")
|
17
20
|
s.require_paths = ['lib']
|
18
21
|
|
19
|
-
s.add_dependency 'activerecord', '>=
|
20
|
-
s.add_dependency 'activesupport', '>=
|
21
|
-
s.add_dependency 'arel', '>= 6'
|
22
|
+
s.add_dependency 'activerecord', '>= 5.2'
|
23
|
+
s.add_dependency 'activesupport', '>= 5.2'
|
22
24
|
|
23
|
-
s.add_development_dependency 'codeclimate-test-reporter'
|
24
25
|
s.add_development_dependency 'pry'
|
25
26
|
s.add_development_dependency 'rake'
|
26
|
-
s.add_development_dependency 'rspec'
|
27
|
+
s.add_development_dependency 'rspec'
|
27
28
|
s.add_development_dependency 'rubocop'
|
29
|
+
s.add_development_dependency 'rubocop-performance'
|
30
|
+
s.add_development_dependency 'rubocop-rails'
|
31
|
+
s.add_development_dependency 'rubocop-rake'
|
32
|
+
s.add_development_dependency 'rubocop-rspec'
|
28
33
|
s.add_development_dependency 'simplecov'
|
29
|
-
s.add_development_dependency '
|
34
|
+
s.add_development_dependency 'simplecov-lcov'
|
35
|
+
s.add_development_dependency 'undercover'
|
36
|
+
s.add_development_dependency 'warning'
|
37
|
+
s.add_development_dependency 'with_model'
|
30
38
|
|
31
|
-
s.required_ruby_version = '>= 2.
|
39
|
+
s.required_ruby_version = '>= 2.6'
|
32
40
|
end
|
data/spec/.rubocop.yml
CHANGED