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,14 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "spec_helper"
|
2
4
|
|
5
|
+
# rubocop:disable RSpec/NestedGroups
|
3
6
|
describe PgSearch::Normalizer do
|
4
7
|
describe "#add_normalization" do
|
5
8
|
context "when config[:ignore] includes :accents" do
|
6
9
|
context "when passed an Arel node" do
|
7
10
|
it "wraps the expression in unaccent()" do
|
8
|
-
config =
|
11
|
+
config = instance_double("PgSearch::Configuration", "config", ignore: [:accents])
|
9
12
|
node = Arel::Nodes::NamedFunction.new("foo", [Arel::Nodes.build_quoted("bar")])
|
10
13
|
|
11
|
-
normalizer =
|
14
|
+
normalizer = described_class.new(config)
|
12
15
|
expect(normalizer.add_normalization(node)).to eq("unaccent(foo('bar'))")
|
13
16
|
end
|
14
17
|
|
@@ -17,9 +20,9 @@ describe PgSearch::Normalizer do
|
|
17
20
|
allow(PgSearch).to receive(:unaccent_function).and_return("my_unaccent")
|
18
21
|
node = Arel::Nodes::NamedFunction.new("foo", [Arel::Nodes.build_quoted("bar")])
|
19
22
|
|
20
|
-
config =
|
23
|
+
config = instance_double("PgSearch::Configuration", "config", ignore: [:accents])
|
21
24
|
|
22
|
-
normalizer =
|
25
|
+
normalizer = described_class.new(config)
|
23
26
|
expect(normalizer.add_normalization(node)).to eq("my_unaccent(foo('bar'))")
|
24
27
|
end
|
25
28
|
end
|
@@ -27,9 +30,9 @@ describe PgSearch::Normalizer do
|
|
27
30
|
|
28
31
|
context "when passed a String" do
|
29
32
|
it "wraps the expression in unaccent()" do
|
30
|
-
config =
|
33
|
+
config = instance_double("PgSearch::Configuration", "config", ignore: [:accents])
|
31
34
|
|
32
|
-
normalizer =
|
35
|
+
normalizer = described_class.new(config)
|
33
36
|
expect(normalizer.add_normalization("foo")).to eq("unaccent(foo)")
|
34
37
|
end
|
35
38
|
|
@@ -37,9 +40,9 @@ describe PgSearch::Normalizer do
|
|
37
40
|
it "wraps the expression in that function" do
|
38
41
|
allow(PgSearch).to receive(:unaccent_function).and_return("my_unaccent")
|
39
42
|
|
40
|
-
config =
|
43
|
+
config = instance_double("PgSearch::Configuration", "config", ignore: [:accents])
|
41
44
|
|
42
|
-
normalizer =
|
45
|
+
normalizer = described_class.new(config)
|
43
46
|
expect(normalizer.add_normalization("foo")).to eq("my_unaccent(foo)")
|
44
47
|
end
|
45
48
|
end
|
@@ -48,11 +51,12 @@ describe PgSearch::Normalizer do
|
|
48
51
|
|
49
52
|
context "when config[:ignore] does not include :accents" do
|
50
53
|
it "passes the expression through" do
|
51
|
-
config =
|
54
|
+
config = instance_double("PgSearch::Configuration", "config", ignore: [])
|
52
55
|
|
53
|
-
normalizer =
|
56
|
+
normalizer = described_class.new(config)
|
54
57
|
expect(normalizer.add_normalization("foo")).to eq("foo")
|
55
58
|
end
|
56
59
|
end
|
57
60
|
end
|
58
61
|
end
|
62
|
+
# rubocop:enable RSpec/NestedGroups
|
data/spec/lib/pg_search_spec.rb
CHANGED
@@ -1,69 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "spec_helper"
|
2
4
|
|
3
|
-
# For
|
5
|
+
# For Active Record 5.x, the association reflection's cache needs be cleared
|
4
6
|
# because we're stubbing the related constants.
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
def clear_searchable_cache
|
12
|
-
end
|
7
|
+
if ActiveRecord::VERSION::MAJOR == 5
|
8
|
+
def clear_searchable_cache
|
9
|
+
PgSearch::Document.reflect_on_association(:searchable).clear_association_scope_cache
|
10
|
+
end
|
11
|
+
else
|
12
|
+
def clear_searchable_cache
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
+
# rubocop:disable RSpec/NestedGroups
|
16
17
|
describe PgSearch do
|
17
18
|
describe ".multisearch" do
|
18
|
-
with_table "pg_search_documents",
|
19
|
+
with_table "pg_search_documents", &DOCUMENTS_SCHEMA
|
19
20
|
|
20
21
|
describe "delegation to PgSearch::Document.search" do
|
21
|
-
subject {
|
22
|
+
subject { described_class.multisearch(query) }
|
23
|
+
|
24
|
+
let(:query) { instance_double("String", "query") }
|
25
|
+
let(:relation) { instance_double("ActiveRecord::Relation", "relation") }
|
22
26
|
|
23
|
-
let(:query) { double(:query) }
|
24
|
-
let(:relation) { double(:relation) }
|
25
27
|
before do
|
26
|
-
|
28
|
+
allow(PgSearch::Document).to receive(:search).with(query).and_return(relation)
|
27
29
|
end
|
28
30
|
|
29
31
|
it { is_expected.to eq(relation) }
|
30
32
|
end
|
31
33
|
|
32
34
|
context "with PgSearch.multisearch_options set to a Hash" do
|
33
|
-
before { allow(PgSearch).to receive(:multisearch_options).and_return(:using => :dmetaphone) }
|
34
35
|
subject do
|
35
|
-
|
36
|
-
|
36
|
+
clear_searchable_cache
|
37
|
+
described_class.multisearch(query).map(&:searchable)
|
37
38
|
end
|
38
39
|
|
40
|
+
before { allow(described_class).to receive(:multisearch_options).and_return(using: :dmetaphone) }
|
41
|
+
|
39
42
|
with_model :MultisearchableModel do
|
40
43
|
table do |t|
|
41
44
|
t.string :title
|
42
45
|
end
|
43
46
|
model do
|
44
|
-
include PgSearch
|
45
|
-
multisearchable :
|
47
|
+
include PgSearch::Model
|
48
|
+
multisearchable against: :title
|
46
49
|
end
|
47
50
|
end
|
48
51
|
|
49
|
-
let!(:soundalike_record) { MultisearchableModel.create!(:
|
52
|
+
let!(:soundalike_record) { MultisearchableModel.create!(title: 'foning') }
|
50
53
|
let(:query) { "Phoning" }
|
54
|
+
|
51
55
|
it { is_expected.to include(soundalike_record) }
|
52
56
|
end
|
53
57
|
|
54
58
|
context "with PgSearch.multisearch_options set to a Proc" do
|
55
59
|
subject do
|
56
|
-
|
57
|
-
|
60
|
+
clear_searchable_cache
|
61
|
+
described_class.multisearch(query, soundalike).map(&:searchable)
|
58
62
|
end
|
59
63
|
|
60
64
|
before do
|
61
|
-
allow(
|
65
|
+
allow(described_class).to receive(:multisearch_options) do
|
62
66
|
lambda do |query, soundalike|
|
63
67
|
if soundalike
|
64
|
-
{:
|
68
|
+
{ using: :dmetaphone, query: query }
|
65
69
|
else
|
66
|
-
{:query
|
70
|
+
{ query: query }
|
67
71
|
end
|
68
72
|
end
|
69
73
|
end
|
@@ -74,26 +78,28 @@ describe PgSearch do
|
|
74
78
|
t.string :title
|
75
79
|
end
|
76
80
|
model do
|
77
|
-
include PgSearch
|
78
|
-
multisearchable :
|
81
|
+
include PgSearch::Model
|
82
|
+
multisearchable against: :title
|
79
83
|
end
|
80
84
|
end
|
81
85
|
|
82
|
-
let!(:soundalike_record) { MultisearchableModel.create!(:
|
86
|
+
let!(:soundalike_record) { MultisearchableModel.create!(title: 'foning') }
|
83
87
|
let(:query) { "Phoning" }
|
84
88
|
|
85
89
|
context "with soundalike true" do
|
86
90
|
let(:soundalike) { true }
|
91
|
+
|
87
92
|
it { is_expected.to include(soundalike_record) }
|
88
93
|
end
|
89
94
|
|
90
95
|
context "with soundalike false" do
|
91
96
|
let(:soundalike) { false }
|
97
|
+
|
92
98
|
it { is_expected.not_to include(soundalike_record) }
|
93
99
|
end
|
94
100
|
end
|
95
101
|
|
96
|
-
context "on an STI subclass" do
|
102
|
+
context "when on an STI subclass" do
|
97
103
|
context "with standard type column" do
|
98
104
|
with_model :SuperclassModel do
|
99
105
|
table do |t|
|
@@ -104,8 +110,8 @@ describe PgSearch do
|
|
104
110
|
|
105
111
|
before do
|
106
112
|
searchable_subclass_model = Class.new(SuperclassModel) do
|
107
|
-
include PgSearch
|
108
|
-
multisearchable :
|
113
|
+
include PgSearch::Model
|
114
|
+
multisearchable against: :content
|
109
115
|
end
|
110
116
|
stub_const("SearchableSubclassModel", searchable_subclass_model)
|
111
117
|
stub_const("AnotherSearchableSubclassModel", searchable_subclass_model)
|
@@ -113,43 +119,44 @@ describe PgSearch do
|
|
113
119
|
end
|
114
120
|
|
115
121
|
it "returns only results for that subclass" do
|
116
|
-
included = SearchableSubclassModel.create!(:
|
122
|
+
included = SearchableSubclassModel.create!(content: "foo bar")
|
117
123
|
|
118
|
-
SearchableSubclassModel.create!(:
|
119
|
-
SuperclassModel.create!(:
|
120
|
-
SuperclassModel.create!(:
|
121
|
-
NonSearchableSubclassModel.create!(:
|
122
|
-
NonSearchableSubclassModel.create!(:
|
124
|
+
SearchableSubclassModel.create!(content: "baz")
|
125
|
+
SuperclassModel.create!(content: "foo bar")
|
126
|
+
SuperclassModel.create!(content: "baz")
|
127
|
+
NonSearchableSubclassModel.create!(content: "foo bar")
|
128
|
+
NonSearchableSubclassModel.create!(content: "baz")
|
123
129
|
|
124
130
|
expect(SuperclassModel.count).to be 6
|
125
131
|
expect(SearchableSubclassModel.count).to be 2
|
126
132
|
|
127
133
|
expect(PgSearch::Document.count).to be 2
|
128
134
|
|
129
|
-
results =
|
135
|
+
results = described_class.multisearch("foo bar")
|
130
136
|
|
131
137
|
expect(results).to eq [included.pg_search_document]
|
132
138
|
end
|
133
139
|
|
134
140
|
it "updates an existing STI model does not create a new pg_search document" do
|
135
|
-
model = SearchableSubclassModel.create!(:
|
141
|
+
model = SearchableSubclassModel.create!(content: "foo bar")
|
136
142
|
expect(SearchableSubclassModel.count).to eq(1)
|
137
143
|
# We fetch the model from the database again otherwise
|
138
144
|
# the pg_search_document from the cache is used.
|
139
145
|
model = SearchableSubclassModel.find(model.id)
|
140
146
|
model.content = "foo"
|
141
147
|
model.save!
|
142
|
-
results =
|
148
|
+
results = described_class.multisearch("foo")
|
143
149
|
expect(results.size).to eq(SearchableSubclassModel.count)
|
144
150
|
end
|
145
151
|
|
146
|
-
|
147
|
-
|
148
|
-
NonSearchableSubclassModel.create!(:
|
149
|
-
|
150
|
-
|
151
|
-
SuperclassModel.create!(:
|
152
|
-
SuperclassModel.create!(:
|
152
|
+
# rubocop:disable RSpec/MultipleExpectations
|
153
|
+
specify "reindexing works" do
|
154
|
+
NonSearchableSubclassModel.create!(content: "foo bar")
|
155
|
+
NonSearchableSubclassModel.create!(content: "baz")
|
156
|
+
expected = SearchableSubclassModel.create!(content: "baz")
|
157
|
+
SuperclassModel.create!(content: "foo bar")
|
158
|
+
SuperclassModel.create!(content: "baz")
|
159
|
+
SuperclassModel.create!(content: "baz2")
|
153
160
|
|
154
161
|
expect(SuperclassModel.count).to be 6
|
155
162
|
expect(NonSearchableSubclassModel.count).to be 2
|
@@ -159,22 +166,23 @@ describe PgSearch do
|
|
159
166
|
|
160
167
|
PgSearch::Multisearch.rebuild(SearchableSubclassModel)
|
161
168
|
|
162
|
-
|
169
|
+
clear_searchable_cache
|
163
170
|
expect(PgSearch::Document.count).to be 1
|
164
171
|
expect(PgSearch::Document.first.searchable.class).to be SearchableSubclassModel
|
165
172
|
expect(PgSearch::Document.first.searchable).to eq expected
|
166
173
|
end
|
174
|
+
# rubocop:enable RSpec/MultipleExpectations
|
167
175
|
|
168
176
|
it "reindexing searchable STI doesn't clobber other related STI models" do
|
169
|
-
SearchableSubclassModel.create!(:
|
170
|
-
AnotherSearchableSubclassModel.create!(:
|
177
|
+
SearchableSubclassModel.create!(content: "baz")
|
178
|
+
AnotherSearchableSubclassModel.create!(content: "baz")
|
171
179
|
|
172
180
|
expect(PgSearch::Document.count).to be 2
|
173
181
|
PgSearch::Multisearch.rebuild(SearchableSubclassModel)
|
174
182
|
expect(PgSearch::Document.count).to be 2
|
175
183
|
|
176
|
-
|
177
|
-
classes = PgSearch::Document.all.collect {|d| d.searchable.class }
|
184
|
+
clear_searchable_cache
|
185
|
+
classes = PgSearch::Document.all.collect { |d| d.searchable.class }
|
178
186
|
expect(classes).to include SearchableSubclassModel
|
179
187
|
expect(classes).to include AnotherSearchableSubclassModel
|
180
188
|
end
|
@@ -194,8 +202,8 @@ describe PgSearch do
|
|
194
202
|
|
195
203
|
before do
|
196
204
|
searchable_subclass_model = Class.new(SuperclassModel) do
|
197
|
-
include PgSearch
|
198
|
-
multisearchable :
|
205
|
+
include PgSearch::Model
|
206
|
+
multisearchable against: :content
|
199
207
|
end
|
200
208
|
stub_const("SearchableSubclassModel", searchable_subclass_model)
|
201
209
|
stub_const("AnotherSearchableSubclassModel", searchable_subclass_model)
|
@@ -203,20 +211,20 @@ describe PgSearch do
|
|
203
211
|
end
|
204
212
|
|
205
213
|
it "returns only results for that subclass" do
|
206
|
-
included = SearchableSubclassModel.create!(:
|
214
|
+
included = SearchableSubclassModel.create!(content: "foo bar")
|
207
215
|
|
208
|
-
SearchableSubclassModel.create!(:
|
209
|
-
SuperclassModel.create!(:
|
210
|
-
SuperclassModel.create!(:
|
211
|
-
NonSearchableSubclassModel.create!(:
|
212
|
-
NonSearchableSubclassModel.create!(:
|
216
|
+
SearchableSubclassModel.create!(content: "baz")
|
217
|
+
SuperclassModel.create!(content: "foo bar")
|
218
|
+
SuperclassModel.create!(content: "baz")
|
219
|
+
NonSearchableSubclassModel.create!(content: "foo bar")
|
220
|
+
NonSearchableSubclassModel.create!(content: "baz")
|
213
221
|
|
214
222
|
expect(SuperclassModel.count).to be 6
|
215
223
|
expect(SearchableSubclassModel.count).to be 2
|
216
224
|
|
217
225
|
expect(PgSearch::Document.count).to be 2
|
218
226
|
|
219
|
-
results =
|
227
|
+
results = described_class.multisearch("foo bar")
|
220
228
|
|
221
229
|
expect(results).to eq [included.pg_search_document]
|
222
230
|
end
|
@@ -225,57 +233,62 @@ describe PgSearch do
|
|
225
233
|
end
|
226
234
|
|
227
235
|
describe ".disable_multisearch" do
|
228
|
-
it "
|
229
|
-
|
230
|
-
|
231
|
-
|
236
|
+
it "disables multisearch temporarily" do
|
237
|
+
multisearch_enabled_before = described_class.multisearch_enabled?
|
238
|
+
multisearch_enabled_inside = nil
|
239
|
+
described_class.disable_multisearch do
|
240
|
+
multisearch_enabled_inside = described_class.multisearch_enabled?
|
232
241
|
end
|
233
|
-
|
242
|
+
multisearch_enabled_after = described_class.multisearch_enabled?
|
234
243
|
|
235
|
-
expect(
|
236
|
-
expect(
|
237
|
-
expect(
|
244
|
+
expect(multisearch_enabled_before).to be(true)
|
245
|
+
expect(multisearch_enabled_inside).to be(false)
|
246
|
+
expect(multisearch_enabled_after).to be(true)
|
238
247
|
end
|
239
248
|
|
240
|
-
it "
|
241
|
-
|
249
|
+
it "reenables multisearch after an error" do
|
250
|
+
multisearch_enabled_before = described_class.multisearch_enabled?
|
251
|
+
multisearch_enabled_inside = nil
|
242
252
|
begin
|
243
|
-
|
244
|
-
|
253
|
+
described_class.disable_multisearch do
|
254
|
+
multisearch_enabled_inside = described_class.multisearch_enabled?
|
245
255
|
raise
|
246
256
|
end
|
247
257
|
rescue StandardError
|
248
258
|
end
|
259
|
+
multisearch_enabled_after = described_class.multisearch_enabled?
|
249
260
|
|
250
|
-
|
251
|
-
|
252
|
-
expect(
|
253
|
-
expect(@multisearch_enabled_inside).to be(false)
|
254
|
-
expect(@multisearch_enabled_after).to be(true)
|
261
|
+
expect(multisearch_enabled_before).to be(true)
|
262
|
+
expect(multisearch_enabled_inside).to be(false)
|
263
|
+
expect(multisearch_enabled_after).to be(true)
|
255
264
|
end
|
256
265
|
|
257
|
-
|
266
|
+
# rubocop:disable RSpec/ExampleLength
|
267
|
+
it "does not disable multisearch on other threads" do
|
258
268
|
values = Queue.new
|
259
269
|
sync = Queue.new
|
260
270
|
Thread.new do
|
261
|
-
values.push
|
271
|
+
values.push described_class.multisearch_enabled?
|
262
272
|
sync.pop # wait
|
263
|
-
values.push
|
273
|
+
values.push described_class.multisearch_enabled?
|
264
274
|
sync.pop # wait
|
265
|
-
values.push
|
275
|
+
values.push described_class.multisearch_enabled?
|
266
276
|
end
|
267
277
|
|
268
|
-
|
269
|
-
|
278
|
+
multisearch_enabled_before = values.pop
|
279
|
+
multisearch_enabled_inside = nil
|
280
|
+
described_class.disable_multisearch do
|
270
281
|
sync.push :go
|
271
|
-
|
282
|
+
multisearch_enabled_inside = values.pop
|
272
283
|
end
|
273
284
|
sync.push :go
|
274
|
-
|
285
|
+
multisearch_enabled_after = values.pop
|
275
286
|
|
276
|
-
expect(
|
277
|
-
expect(
|
278
|
-
expect(
|
287
|
+
expect(multisearch_enabled_before).to be(true)
|
288
|
+
expect(multisearch_enabled_inside).to be(true)
|
289
|
+
expect(multisearch_enabled_after).to be(true)
|
279
290
|
end
|
291
|
+
# rubocop:enable RSpec/ExampleLength
|
280
292
|
end
|
281
293
|
end
|
294
|
+
# rubocop:enable RSpec/NestedGroups
|
data/spec/spec_helper.rb
CHANGED
@@ -1,16 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'warning'
|
4
|
+
# Ignore Ruby 2.7 warnings from Active Record
|
5
|
+
Warning.ignore :keyword_separation
|
6
|
+
|
7
|
+
# https://github.com/grodowski/undercover#setting-up-required-lcov-reporting
|
1
8
|
require 'simplecov'
|
2
|
-
|
9
|
+
require 'simplecov-lcov'
|
10
|
+
SimpleCov::Formatter::LcovFormatter.config.report_with_single_file = true
|
11
|
+
SimpleCov.formatter = SimpleCov::Formatter::LcovFormatter
|
12
|
+
SimpleCov.start do
|
13
|
+
add_filter(%r{^/spec/})
|
14
|
+
enable_coverage(:branch)
|
15
|
+
end
|
16
|
+
require 'undercover'
|
3
17
|
|
4
18
|
require "bundler/setup"
|
5
19
|
require "pg_search"
|
6
20
|
|
7
21
|
RSpec.configure do |config|
|
8
|
-
config.expect_with :rspec do |
|
9
|
-
|
22
|
+
config.expect_with :rspec do |expects|
|
23
|
+
expects.syntax = :expect
|
10
24
|
end
|
11
25
|
|
12
|
-
config.mock_with :rspec do |
|
13
|
-
|
26
|
+
config.mock_with :rspec do |mocks|
|
27
|
+
mocks.syntax = :expect
|
28
|
+
mocks.verify_doubled_constant_names = true
|
29
|
+
mocks.verify_partial_doubles = true
|
14
30
|
end
|
15
31
|
|
16
32
|
config.example_status_persistence_file_path = 'tmp/examples.txt'
|
@@ -20,7 +36,10 @@ require 'support/database'
|
|
20
36
|
require 'support/with_model'
|
21
37
|
|
22
38
|
DOCUMENTS_SCHEMA = lambda do |t|
|
23
|
-
t.belongs_to :searchable, :
|
39
|
+
t.belongs_to :searchable, polymorphic: true, index: true
|
24
40
|
t.text :content
|
25
41
|
t.timestamps null: false
|
42
|
+
|
43
|
+
# Used to test additional_attributes setup
|
44
|
+
t.text :additional_attribute_column
|
26
45
|
end
|
data/spec/support/database.rb
CHANGED
@@ -1,27 +1,24 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
case RUBY_PLATFORM
|
4
|
+
when "java"
|
2
5
|
require "activerecord-jdbc-adapter"
|
3
|
-
|
6
|
+
ERROR_CLASS = ActiveRecord::JDBCError
|
4
7
|
else
|
5
8
|
require "pg"
|
6
|
-
|
9
|
+
ERROR_CLASS = PG::Error
|
7
10
|
end
|
8
11
|
|
9
|
-
error_classes << ActiveRecord::NoDatabaseError if defined? ActiveRecord::NoDatabaseError
|
10
|
-
|
11
12
|
begin
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
ActiveRecord::Base.establish_connection(:adapter => 'postgresql',
|
19
|
-
:database => 'pg_search_test',
|
20
|
-
:username => database_user,
|
21
|
-
:min_messages => 'warning')
|
13
|
+
connection_options = { adapter: 'postgresql', database: 'pg_search_test', min_messages: 'warning' }
|
14
|
+
if ENV["CI"]
|
15
|
+
connection_options[:username] = 'postgres'
|
16
|
+
connection_options[:password] = 'postgres'
|
17
|
+
end
|
18
|
+
ActiveRecord::Base.establish_connection(connection_options)
|
22
19
|
connection = ActiveRecord::Base.connection
|
23
20
|
connection.execute("SELECT 1")
|
24
|
-
rescue
|
21
|
+
rescue ERROR_CLASS, ActiveRecord::NoDatabaseError => e
|
25
22
|
at_exit do
|
26
23
|
puts "-" * 80
|
27
24
|
puts "Unable to connect to database. Please run:"
|
@@ -29,31 +26,32 @@ rescue *error_classes => exception
|
|
29
26
|
puts " createdb pg_search_test"
|
30
27
|
puts "-" * 80
|
31
28
|
end
|
32
|
-
raise
|
29
|
+
raise e
|
33
30
|
end
|
34
31
|
|
35
32
|
if ENV["LOGGER"]
|
36
33
|
require "logger"
|
37
|
-
ActiveRecord::Base.logger = Logger.new(
|
34
|
+
ActiveRecord::Base.logger = Logger.new($stdout)
|
38
35
|
end
|
39
36
|
|
40
37
|
def install_extension(name)
|
41
38
|
connection = ActiveRecord::Base.connection
|
42
39
|
extension = connection.execute "SELECT * FROM pg_catalog.pg_extension WHERE extname = '#{name}';"
|
43
40
|
return unless extension.none?
|
41
|
+
|
44
42
|
connection.execute "CREATE EXTENSION #{name};"
|
45
|
-
rescue StandardError =>
|
43
|
+
rescue StandardError => e
|
46
44
|
at_exit do
|
47
45
|
puts "-" * 80
|
48
46
|
puts "Please install the #{name} extension"
|
49
47
|
puts "-" * 80
|
50
48
|
end
|
51
|
-
raise
|
49
|
+
raise e
|
52
50
|
end
|
53
51
|
|
54
52
|
def install_extension_if_missing(name, query, expected_result)
|
55
53
|
result = ActiveRecord::Base.connection.select_value(query)
|
56
|
-
raise "Unexpected output for #{query}: #{result.inspect}" unless result.
|
54
|
+
raise "Unexpected output for #{query}: #{result.inspect}" unless result.casecmp(expected_result).zero?
|
57
55
|
rescue StandardError
|
58
56
|
install_extension(name)
|
59
57
|
end
|