pg_search 0.7.9 → 1.0.0
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/.bundle/config +2 -0
- data/.gitignore +7 -9
- data/.rubocop.yml +3 -3
- data/.rubocop_todo.yml +1 -5
- data/CHANGELOG.md +7 -1
- data/LICENSE +1 -1
- data/README.md +23 -8
- data/lib/pg_search/compatibility.rb +0 -6
- data/lib/pg_search/configuration.rb +1 -1
- data/lib/pg_search/migration/templates/create_pg_search_documents.rb.erb +1 -1
- data/lib/pg_search/scope_options.rb +32 -10
- data/lib/pg_search/version.rb +1 -1
- data/lib/pg_search.rb +26 -1
- data/pg_search.gemspec +1 -1
- data/spec/integration/associations_spec.rb +8 -3
- data/spec/integration/pg_search_spec.rb +137 -233
- data/spec/lib/pg_search_spec.rb +221 -0
- data/spec/spec_helper.rb +1 -1
- metadata +7 -7
- data/bin/guard +0 -16
- data/bin/rake +0 -16
- data/bin/rspec +0 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f2c1314fe8a375215c28cab705710050ceffcef3
|
4
|
+
data.tar.gz: 4055f33418dfca0cbb94259b0a3fb0befc53342c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7ce28204b8e03ecaf75d5d65d810f84d20a4104fd82a9eafed9e4abcc25849466861b86075fab54212c6974228f1a8b873ac2aa805e74d46c0f15d25d9040588
|
7
|
+
data.tar.gz: de01412dbad07868ed1f71ad29bb992fcfa7b085e2cf9301e5c47c2afacbf16de7c6f602692c60e474a77bc15dd26b4405c9a2f59773262f75141cc749b338f0
|
data/.bundle/config
ADDED
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
data/.rubocop_todo.yml
CHANGED
@@ -58,7 +58,7 @@ Style/BlockEndNewline:
|
|
58
58
|
|
59
59
|
# Offense count: 14
|
60
60
|
# Cop supports --auto-correct.
|
61
|
-
Style/
|
61
|
+
Style/BlockDelimiters:
|
62
62
|
Enabled: false
|
63
63
|
|
64
64
|
# Offense count: 1
|
@@ -194,10 +194,6 @@ Style/RaiseArgs:
|
|
194
194
|
Style/RedundantReturn:
|
195
195
|
Enabled: false
|
196
196
|
|
197
|
-
# Offense count: 2
|
198
|
-
Style/RegexpLiteral:
|
199
|
-
MaxSlashes: 0
|
200
|
-
|
201
197
|
# Offense count: 10
|
202
198
|
# Cop supports --auto-correct.
|
203
199
|
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
data/CHANGELOG.md
CHANGED
@@ -1,8 +1,14 @@
|
|
1
1
|
# pg_search changelog
|
2
2
|
|
3
|
+
## 1.0.0
|
4
|
+
|
5
|
+
* Support more `ActiveRecord::Relation` methods, such as `#pluck` and `#select` by moving search-related operations to subquery.
|
6
|
+
* Generate index by default in migration for `pg_search_documents` table.
|
7
|
+
* Start officially using [Semantic Versioning 2.0.0](http://semver.org/spec/v2.0.0.html).
|
8
|
+
|
3
9
|
## 0.7.9
|
4
10
|
|
5
|
-
* Improve support for single table inheritance (STI) models (Ewan McDougall)
|
11
|
+
* Improve support for single table inheritance (STI) models. (Ewan McDougall)
|
6
12
|
|
7
13
|
## 0.7.8
|
8
14
|
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -5,6 +5,7 @@
|
|
5
5
|
[](https://rubygems.org/gems/pg_search)
|
6
6
|
[](https://gemnasium.com/Casecommons/pg_search)
|
7
7
|
[](http://inch-ci.org/github/Casecommons/pg_search)
|
8
|
+
[](https://gitter.im/Casecommons/pg_search?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
8
9
|
|
9
10
|
## DESCRIPTION
|
10
11
|
|
@@ -24,13 +25,17 @@ Read the blog post introducing PgSearch at http://pivotallabs.com/pg-search/
|
|
24
25
|
|
25
26
|
## INSTALL
|
26
27
|
|
27
|
-
|
28
|
+
```bash
|
29
|
+
$ gem install pg_search
|
30
|
+
```
|
28
31
|
|
29
32
|
### Rails 3.1, 3.2, 4.0 or later, Ruby 1.9.2, 2.0, or later
|
30
33
|
|
31
34
|
In Gemfile
|
32
35
|
|
33
|
-
|
36
|
+
```ruby
|
37
|
+
gem 'pg_search'
|
38
|
+
```
|
34
39
|
|
35
40
|
### Rails 3.0
|
36
41
|
|
@@ -38,7 +43,9 @@ The newest versions of PgSearch no longer support Rails 3.0. However, the 0.5
|
|
38
43
|
series still works. It's not actively maintained, but submissions are welcome
|
39
44
|
for backports and bugfixes.
|
40
45
|
|
41
|
-
|
46
|
+
```ruby
|
47
|
+
gem 'pg_search', "~> 0.5.7"
|
48
|
+
```
|
42
49
|
|
43
50
|
The 0.5 branch lives at
|
44
51
|
https://github.com/Casecommons/pg_search/tree/0.5-stable
|
@@ -49,7 +56,9 @@ The newest versions of PgSearch no longer support Rails 2. However, the 0.2
|
|
49
56
|
series still works. It's not actively maintained, but submissions are welcome
|
50
57
|
for backports and bugfixes.
|
51
58
|
|
52
|
-
|
59
|
+
```ruby
|
60
|
+
gem 'pg_search', "~> 0.2.0"
|
61
|
+
```
|
53
62
|
|
54
63
|
The 0.2 branch lives at
|
55
64
|
https://github.com/Casecommons/pg_search/tree/0.2-stable
|
@@ -60,7 +69,9 @@ In addition to installing and requiring the gem, you may want to include the
|
|
60
69
|
PgSearch rake tasks in your Rakefile. This isn't necessary for Rails projects,
|
61
70
|
which gain the Rake tasks via a Railtie.
|
62
71
|
|
63
|
-
|
72
|
+
```ruby
|
73
|
+
load "pg_search/tasks.rb"
|
74
|
+
```
|
64
75
|
|
65
76
|
### Ruby 1.8.7 or earlier
|
66
77
|
|
@@ -68,7 +79,9 @@ The newest versions of PgSearch no longer support Ruby 1.8.7. However, the 0.6
|
|
68
79
|
series still works. It's not actively maintained, but submissions are welcome
|
69
80
|
for backports and bugfixes.
|
70
81
|
|
71
|
-
|
82
|
+
```ruby
|
83
|
+
gem 'pg_search', "~> 0.6.4"
|
84
|
+
```
|
72
85
|
|
73
86
|
The 0.6 branch lives at
|
74
87
|
https://github.com/Casecommons/pg_search/tree/0.6-stable
|
@@ -105,8 +118,10 @@ search.
|
|
105
118
|
Before using multi-search, you must generate and run a migration to create the
|
106
119
|
pg_search_documents database table.
|
107
120
|
|
108
|
-
|
109
|
-
|
121
|
+
```bash
|
122
|
+
$ rails g pg_search:migration:multisearch
|
123
|
+
$ rake db:migrate
|
124
|
+
```
|
110
125
|
|
111
126
|
#### multisearchable
|
112
127
|
|
@@ -3,7 +3,7 @@ class CreatePgSearchDocuments < ActiveRecord::Migration
|
|
3
3
|
say_with_time("Creating table for pg_search multisearch") do
|
4
4
|
create_table :pg_search_documents do |t|
|
5
5
|
t.text :content
|
6
|
-
t.belongs_to :searchable, :polymorphic => true
|
6
|
+
t.belongs_to :searchable, :polymorphic => true, :index => true
|
7
7
|
t.timestamps null: false
|
8
8
|
end
|
9
9
|
end
|
@@ -4,7 +4,7 @@ require "active_support/core_ext/module/delegation"
|
|
4
4
|
|
5
5
|
module PgSearch
|
6
6
|
class ScopeOptions
|
7
|
-
attr_reader :config, :feature_options
|
7
|
+
attr_reader :config, :feature_options, :model
|
8
8
|
|
9
9
|
def initialize(config)
|
10
10
|
@config = config
|
@@ -13,12 +13,11 @@ module PgSearch
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def apply(scope)
|
16
|
-
scope
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
extend(DisableEagerLoading)
|
16
|
+
scope
|
17
|
+
.joins(rank_join)
|
18
|
+
.order("pg_search.rank DESC, #{order_within_rank}")
|
19
|
+
.extend(DisableEagerLoading)
|
20
|
+
.extend(WithPgSearchRank)
|
22
21
|
end
|
23
22
|
|
24
23
|
# workaround for https://github.com/Casecommons/pg_search/issues/14
|
@@ -28,9 +27,28 @@ module PgSearch
|
|
28
27
|
end
|
29
28
|
end
|
30
29
|
|
30
|
+
module WithPgSearchRank
|
31
|
+
def with_pg_search_rank
|
32
|
+
scope = self
|
33
|
+
scope = scope.select("*") unless scope.select_values.any?
|
34
|
+
scope.select("pg_search.rank AS pg_search_rank")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
31
38
|
private
|
32
39
|
|
33
|
-
delegate :connection, :quoted_table_name, :to =>
|
40
|
+
delegate :connection, :quoted_table_name, :to => :model
|
41
|
+
|
42
|
+
def subquery
|
43
|
+
model
|
44
|
+
.except(:select)
|
45
|
+
.select("#{primary_key} AS pg_search_id")
|
46
|
+
.select("#{rank} AS rank")
|
47
|
+
.joins(subquery_join)
|
48
|
+
.where(conditions)
|
49
|
+
.limit(nil)
|
50
|
+
.offset(nil)
|
51
|
+
end
|
34
52
|
|
35
53
|
def conditions
|
36
54
|
config.features.reject do |feature_name, feature_options|
|
@@ -47,10 +65,10 @@ module PgSearch
|
|
47
65
|
end
|
48
66
|
|
49
67
|
def primary_key
|
50
|
-
"#{quoted_table_name}.#{connection.quote_column_name(
|
68
|
+
"#{quoted_table_name}.#{connection.quote_column_name(model.primary_key)}"
|
51
69
|
end
|
52
70
|
|
53
|
-
def
|
71
|
+
def subquery_join
|
54
72
|
if config.associations.any?
|
55
73
|
config.associations.map do |association|
|
56
74
|
association.join(primary_key)
|
@@ -86,5 +104,9 @@ module PgSearch
|
|
86
104
|
feature_for($1).rank.to_sql
|
87
105
|
end
|
88
106
|
end
|
107
|
+
|
108
|
+
def rank_join
|
109
|
+
"INNER JOIN (#{subquery.to_sql}) pg_search ON #{primary_key} = pg_search.pg_search_id"
|
110
|
+
end
|
89
111
|
end
|
90
112
|
end
|
data/lib/pg_search/version.rb
CHANGED
data/lib/pg_search.rb
CHANGED
@@ -15,7 +15,6 @@ require "pg_search/version"
|
|
15
15
|
|
16
16
|
module PgSearch
|
17
17
|
extend ActiveSupport::Concern
|
18
|
-
include Compatibility::ActiveRecord3 if ActiveRecord::VERSION::MAJOR == 3
|
19
18
|
|
20
19
|
mattr_accessor :multisearch_options
|
21
20
|
self.multisearch_options = {}
|
@@ -75,7 +74,33 @@ module PgSearch
|
|
75
74
|
end
|
76
75
|
end
|
77
76
|
|
77
|
+
def method_missing(symbol, *args)
|
78
|
+
case symbol
|
79
|
+
when :pg_search_rank
|
80
|
+
raise PgSearchRankNotSelected.new unless respond_to?(:pg_search_rank)
|
81
|
+
read_attribute(:pg_search_rank).to_f
|
82
|
+
else
|
83
|
+
super
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def respond_to_missing?(symbol, *args)
|
88
|
+
case symbol
|
89
|
+
when :pg_search_rank
|
90
|
+
attributes.key?(:pg_search_rank)
|
91
|
+
else
|
92
|
+
super
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
|
78
97
|
class NotSupportedForPostgresqlVersion < StandardError; end
|
98
|
+
|
99
|
+
class PgSearchRankNotSelected < StandardError
|
100
|
+
def message
|
101
|
+
"You must chain .with_pg_search_rank after the pg_search_scope to access the pg_search_rank attribute on returned records"
|
102
|
+
end
|
103
|
+
end
|
79
104
|
end
|
80
105
|
|
81
106
|
require "pg_search/document"
|
data/pg_search.gemspec
CHANGED
@@ -25,7 +25,7 @@ Gem::Specification.new do |s|
|
|
25
25
|
s.add_development_dependency 'pry'
|
26
26
|
s.add_development_dependency 'rspec', '~> 3.0'
|
27
27
|
s.add_development_dependency 'with_model', '>= 1.2'
|
28
|
-
s.add_development_dependency 'rubocop'
|
28
|
+
s.add_development_dependency 'rubocop', '>= 0.30.0'
|
29
29
|
|
30
30
|
s.required_ruby_version = ">= 1.9.2"
|
31
31
|
end
|
@@ -117,10 +117,11 @@ describe PgSearch do
|
|
117
117
|
expect(results).not_to include(excluded)
|
118
118
|
end
|
119
119
|
|
120
|
-
it "uses an unscoped relation of the
|
120
|
+
it "uses an unscoped relation of the associated model" do
|
121
121
|
excluded = ModelWithHasMany.create!(:title => 'abcdef', :other_models => [
|
122
122
|
AssociatedModelWithHasMany.create!(:title => 'abcdef')
|
123
123
|
])
|
124
|
+
|
124
125
|
included = [
|
125
126
|
ModelWithHasMany.create!(:title => 'abcdef', :other_models => [
|
126
127
|
AssociatedModelWithHasMany.create!(:title => 'foo'),
|
@@ -128,7 +129,11 @@ describe PgSearch do
|
|
128
129
|
])
|
129
130
|
]
|
130
131
|
|
131
|
-
results = ModelWithHasMany
|
132
|
+
results = ModelWithHasMany
|
133
|
+
.limit(1)
|
134
|
+
.order("#{ModelWithHasMany.quoted_table_name}.id ASC")
|
135
|
+
.with_associated('foo bar')
|
136
|
+
|
132
137
|
expect(results.map(&:title)).to match_array(included.map(&:title))
|
133
138
|
expect(results).not_to include(excluded)
|
134
139
|
end
|
@@ -300,7 +305,7 @@ describe PgSearch do
|
|
300
305
|
|
301
306
|
results = ModelWithAssociation.with_associated('foo bar')
|
302
307
|
|
303
|
-
expect(results.to_sql.scan("INNER JOIN").length).to eq(1)
|
308
|
+
expect(results.to_sql.scan("INNER JOIN #{AssociatedModel.quoted_table_name}").length).to eq(1)
|
304
309
|
included.each { |object| expect(results).to include(object) }
|
305
310
|
excluded.each { |object| expect(results).not_to include(object) }
|
306
311
|
end
|
@@ -135,6 +135,57 @@ describe "an Active Record model which includes PgSearch" do
|
|
135
135
|
ModelWithPgSearch.pg_search_scope :search_content, :against => :content
|
136
136
|
end
|
137
137
|
|
138
|
+
context "when chained after a select() scope" do
|
139
|
+
it "honors the select" do
|
140
|
+
included = ModelWithPgSearch.create!(content: 'foo', title: 'bar')
|
141
|
+
excluded = ModelWithPgSearch.create!(content: 'bar', title: 'foo')
|
142
|
+
|
143
|
+
results = ModelWithPgSearch.select('id, title').search_content('foo')
|
144
|
+
|
145
|
+
expect(results).to include(included)
|
146
|
+
expect(results).to_not include(excluded)
|
147
|
+
|
148
|
+
expect(results.first.attributes.key?('content')).to eq false
|
149
|
+
|
150
|
+
expect(results.select { |record| record.title == "bar" }).to eq [included]
|
151
|
+
expect(results.select { |record| record.title != "bar" }).to be_empty
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
context "when chained before a select() scope" do
|
156
|
+
it "honors the select" do
|
157
|
+
included = ModelWithPgSearch.create!(content: 'foo', title: 'bar')
|
158
|
+
excluded = ModelWithPgSearch.create!(content: 'bar', title: 'foo')
|
159
|
+
|
160
|
+
results = ModelWithPgSearch.search_content('foo').select('id, title')
|
161
|
+
|
162
|
+
expect(results).to include(included)
|
163
|
+
expect(results).to_not include(excluded)
|
164
|
+
|
165
|
+
expect(results.first.attributes.key?('content')).to eq false
|
166
|
+
|
167
|
+
expect(results.select { |record| record.title == "bar" }).to eq [included]
|
168
|
+
expect(results.select { |record| record.title != "bar" }).to be_empty
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
context "when surrouned by select() scopes" do
|
173
|
+
it "honors the select" do
|
174
|
+
included = ModelWithPgSearch.create!(content: 'foo', title: 'bar')
|
175
|
+
excluded = ModelWithPgSearch.create!(content: 'bar', title: 'foo')
|
176
|
+
|
177
|
+
results = ModelWithPgSearch.select('id').search_content('foo').select('title')
|
178
|
+
|
179
|
+
expect(results).to include(included)
|
180
|
+
expect(results).to_not include(excluded)
|
181
|
+
|
182
|
+
expect(results.first.attributes.key?('content')).to eq false
|
183
|
+
|
184
|
+
expect(results.select { |record| record.title == "bar" }).to eq [included]
|
185
|
+
expect(results.select { |record| record.title != "bar" }).to be_empty
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
138
189
|
it "returns an empty array when a blank query is passed in" do
|
139
190
|
ModelWithPgSearch.create!(:content => 'foo')
|
140
191
|
|
@@ -155,10 +206,50 @@ describe "an Active Record model which includes PgSearch" do
|
|
155
206
|
ModelWithPgSearch.create!(:content => 'foo')
|
156
207
|
ModelWithPgSearch.create!(:content => 'bar')
|
157
208
|
|
209
|
+
results = ModelWithPgSearch.search_content('foo')
|
210
|
+
expect(results.count).to eq 1
|
211
|
+
end
|
212
|
+
|
213
|
+
it "returns the correct count(:all)" do
|
214
|
+
ModelWithPgSearch.create!(:content => 'foo')
|
215
|
+
ModelWithPgSearch.create!(:content => 'bar')
|
216
|
+
|
158
217
|
results = ModelWithPgSearch.search_content('foo')
|
159
218
|
expect(results.count(:all)).to eq 1
|
160
219
|
end
|
161
220
|
|
221
|
+
it "supports #select" do
|
222
|
+
record = ModelWithPgSearch.create!(:content => 'foo')
|
223
|
+
other_record = ModelWithPgSearch.create!(:content => 'bar')
|
224
|
+
|
225
|
+
records_with_only_id = ModelWithPgSearch.search_content('foo').select('id')
|
226
|
+
expect(records_with_only_id.length).to eq 1
|
227
|
+
|
228
|
+
returned_record = records_with_only_id.first
|
229
|
+
|
230
|
+
expect(returned_record.attributes).to eq({"id" => record.id})
|
231
|
+
end
|
232
|
+
|
233
|
+
unless ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR < 2
|
234
|
+
it "supports #pluck" do
|
235
|
+
record = ModelWithPgSearch.create!(:content => 'foo')
|
236
|
+
other_record = ModelWithPgSearch.create!(:content => 'bar')
|
237
|
+
|
238
|
+
ids = ModelWithPgSearch.search_content('foo').pluck('id')
|
239
|
+
expect(ids).to eq [record.id]
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
it "supports adding where clauses using the pg_search.rank" do
|
244
|
+
once = ModelWithPgSearch.create!(:content => 'foo bar')
|
245
|
+
twice = ModelWithPgSearch.create!(:content => 'foo foo')
|
246
|
+
|
247
|
+
records = ModelWithPgSearch.search_content('foo')
|
248
|
+
.where("pg_search.rank > 0.07")
|
249
|
+
|
250
|
+
expect(records).to eq [twice]
|
251
|
+
end
|
252
|
+
|
162
253
|
it "returns rows where the column contains all the terms in the query in any order" do
|
163
254
|
included = [ModelWithPgSearch.create!(:content => 'foo bar'),
|
164
255
|
ModelWithPgSearch.create!(:content => 'bar foo')]
|
@@ -211,7 +302,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
211
302
|
loser = ModelWithPgSearch.create!(:content => 'foo')
|
212
303
|
winner = ModelWithPgSearch.create!(:content => 'foo foo')
|
213
304
|
|
214
|
-
results = ModelWithPgSearch.search_content("foo")
|
305
|
+
results = ModelWithPgSearch.search_content("foo").with_pg_search_rank
|
215
306
|
expect(results[0].pg_search_rank).to be > results[1].pg_search_rank
|
216
307
|
expect(results).to eq([winner, loser])
|
217
308
|
end
|
@@ -426,7 +517,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
426
517
|
it "adds a #pg_search_rank method to each returned model record" do
|
427
518
|
ModelWithPgSearch.pg_search_scope :search_content, :against => :content
|
428
519
|
|
429
|
-
result = ModelWithPgSearch.search_content("Strip Down").first
|
520
|
+
result = ModelWithPgSearch.search_content("Strip Down").with_pg_search_rank.first
|
430
521
|
|
431
522
|
expect(result.pg_search_rank).to be_a(Float)
|
432
523
|
end
|
@@ -441,7 +532,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
441
532
|
end
|
442
533
|
|
443
534
|
it "ranks the results for documents with less text higher" do
|
444
|
-
results = ModelWithPgSearch.search_content_with_normalization("down")
|
535
|
+
results = ModelWithPgSearch.search_content_with_normalization("down").with_pg_search_rank
|
445
536
|
|
446
537
|
expect(results.map(&:content)).to eq(["Down", "Strip Down", "Down and Out", "Won't Let You Down"])
|
447
538
|
expect(results.first.pg_search_rank).to be > results.last.pg_search_rank
|
@@ -456,7 +547,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
456
547
|
end
|
457
548
|
|
458
549
|
it "ranks the results equally" do
|
459
|
-
results = ModelWithPgSearch.search_content_without_normalization("down")
|
550
|
+
results = ModelWithPgSearch.search_content_without_normalization("down").with_pg_search_rank
|
460
551
|
|
461
552
|
expect(results.map(&:content)).to eq(["Strip Down", "Down", "Down and Out", "Won't Let You Down"])
|
462
553
|
expect(results.first.pg_search_rank).to eq(results.last.pg_search_rank)
|
@@ -474,7 +565,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
474
565
|
loser = ModelWithPgSearch.create!(:title => 'bar', :content => 'foo')
|
475
566
|
winner = ModelWithPgSearch.create!(:title => 'foo', :content => 'bar')
|
476
567
|
|
477
|
-
results = ModelWithPgSearch.search_weighted_by_array_of_arrays('foo')
|
568
|
+
results = ModelWithPgSearch.search_weighted_by_array_of_arrays('foo').with_pg_search_rank
|
478
569
|
expect(results[0].pg_search_rank).to be > results[1].pg_search_rank
|
479
570
|
expect(results).to eq([winner, loser])
|
480
571
|
end
|
@@ -490,7 +581,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
490
581
|
loser = ModelWithPgSearch.create!(:title => 'bar', :content => 'foo')
|
491
582
|
winner = ModelWithPgSearch.create!(:title => 'foo', :content => 'bar')
|
492
583
|
|
493
|
-
results = ModelWithPgSearch.search_weighted_by_hash('foo')
|
584
|
+
results = ModelWithPgSearch.search_weighted_by_hash('foo').with_pg_search_rank
|
494
585
|
expect(results[0].pg_search_rank).to be > results[1].pg_search_rank
|
495
586
|
expect(results).to eq([winner, loser])
|
496
587
|
end
|
@@ -506,7 +597,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
506
597
|
loser = ModelWithPgSearch.create!(:title => 'bar', :content => 'foo')
|
507
598
|
winner = ModelWithPgSearch.create!(:title => 'foo', :content => 'bar')
|
508
599
|
|
509
|
-
results = ModelWithPgSearch.search_weighted('foo')
|
600
|
+
results = ModelWithPgSearch.search_weighted('foo').with_pg_search_rank
|
510
601
|
expect(results[0].pg_search_rank).to be > results[1].pg_search_rank
|
511
602
|
expect(results).to eq([winner, loser])
|
512
603
|
end
|
@@ -910,15 +1001,24 @@ describe "an Active Record model which includes PgSearch" do
|
|
910
1001
|
|
911
1002
|
it "should return records with a rank attribute equal to the :ranked_by expression" do
|
912
1003
|
ModelWithPgSearch.create!(:content => 'foo', :importance => 10)
|
913
|
-
results = ModelWithPgSearch.search_content_with_importance_as_rank("foo")
|
1004
|
+
results = ModelWithPgSearch.search_content_with_importance_as_rank("foo").with_pg_search_rank
|
914
1005
|
expect(results.first.pg_search_rank).to eq(10)
|
915
1006
|
end
|
916
1007
|
|
917
1008
|
it "should substitute :tsearch with the tsearch rank expression in the :ranked_by expression" do
|
918
1009
|
ModelWithPgSearch.create!(:content => 'foo', :importance => 10)
|
919
1010
|
|
920
|
-
|
921
|
-
|
1011
|
+
tsearch_result =
|
1012
|
+
ModelWithPgSearch.search_content_with_default_rank("foo").with_pg_search_rank.first
|
1013
|
+
|
1014
|
+
tsearch_rank = tsearch_result.pg_search_rank
|
1015
|
+
|
1016
|
+
multiplied_result =
|
1017
|
+
ModelWithPgSearch.search_content_with_importance_as_rank_multiplier("foo")
|
1018
|
+
.with_pg_search_rank
|
1019
|
+
.first
|
1020
|
+
|
1021
|
+
multiplied_rank = multiplied_result.pg_search_rank
|
922
1022
|
|
923
1023
|
expect(multiplied_rank).to be_within(0.001).of(tsearch_rank * 10)
|
924
1024
|
end
|
@@ -936,17 +1036,39 @@ describe "an Active Record model which includes PgSearch" do
|
|
936
1036
|
|
937
1037
|
%w[tsearch trigram dmetaphone].each do |feature|
|
938
1038
|
context "using the #{feature} ranking algorithm" do
|
939
|
-
|
940
|
-
|
941
|
-
|
1039
|
+
let(:scope_name) { :"search_content_ranked_by_#{feature}" }
|
1040
|
+
before do
|
942
1041
|
ModelWithPgSearch.pg_search_scope scope_name,
|
943
1042
|
:against => :content,
|
944
1043
|
:ranked_by => ":#{feature}"
|
945
1044
|
|
946
1045
|
ModelWithPgSearch.create!(:content => 'foo')
|
1046
|
+
end
|
947
1047
|
|
948
|
-
|
949
|
-
|
1048
|
+
context "when .with_pg_search_rank is chained after" do
|
1049
|
+
specify "its results respond to #pg_search_rank" do
|
1050
|
+
result = ModelWithPgSearch.send(scope_name, 'foo').with_pg_search_rank.first
|
1051
|
+
expect(result).to respond_to(:pg_search_rank)
|
1052
|
+
end
|
1053
|
+
|
1054
|
+
it "returns the rank when #pg_search_rank is called on a result" do
|
1055
|
+
results = ModelWithPgSearch.send(scope_name, 'foo').with_pg_search_rank
|
1056
|
+
expect(results.first.pg_search_rank).to be_a Float
|
1057
|
+
end
|
1058
|
+
end
|
1059
|
+
|
1060
|
+
context "when .with_pg_search_rank is not chained after" do
|
1061
|
+
specify "its results do not respond to #pg_search_rank" do
|
1062
|
+
result = ModelWithPgSearch.send(scope_name, 'foo').first
|
1063
|
+
expect(result).not_to respond_to(:pg_search_rank)
|
1064
|
+
end
|
1065
|
+
|
1066
|
+
it "raises PgSearch::PgSearchRankNotSelected when #pg_search_rank is called on a result" do
|
1067
|
+
result = ModelWithPgSearch.send(scope_name, 'foo').first
|
1068
|
+
expect {
|
1069
|
+
result.pg_search_rank
|
1070
|
+
}.to raise_exception(PgSearch::PgSearchRankNotSelected)
|
1071
|
+
end
|
950
1072
|
end
|
951
1073
|
end
|
952
1074
|
end
|
@@ -1075,222 +1197,4 @@ describe "an Active Record model which includes PgSearch" do
|
|
1075
1197
|
expect(ModelWithPgSearch.pg_search_multisearchable_options).to eq(options)
|
1076
1198
|
end
|
1077
1199
|
end
|
1078
|
-
|
1079
|
-
describe ".multisearch" do
|
1080
|
-
with_table "pg_search_documents", {}, &DOCUMENTS_SCHEMA
|
1081
|
-
|
1082
|
-
describe "delegation to PgSearch::Document.search" do
|
1083
|
-
subject { PgSearch.multisearch(query) }
|
1084
|
-
|
1085
|
-
let(:query) { double(:query) }
|
1086
|
-
let(:relation) { double(:relation) }
|
1087
|
-
before do
|
1088
|
-
expect(PgSearch::Document).to receive(:search).with(query).and_return(relation)
|
1089
|
-
end
|
1090
|
-
|
1091
|
-
it { is_expected.to eq(relation) }
|
1092
|
-
end
|
1093
|
-
|
1094
|
-
context "with PgSearch.multisearch_options set to a Hash" do
|
1095
|
-
before { allow(PgSearch).to receive(:multisearch_options).and_return({:using => :dmetaphone}) }
|
1096
|
-
subject { PgSearch.multisearch(query).map(&:searchable) }
|
1097
|
-
|
1098
|
-
with_model :MultisearchableModel do
|
1099
|
-
table do |t|
|
1100
|
-
t.string :title
|
1101
|
-
end
|
1102
|
-
model do
|
1103
|
-
include PgSearch
|
1104
|
-
multisearchable :against => :title
|
1105
|
-
end
|
1106
|
-
end
|
1107
|
-
|
1108
|
-
let!(:soundalike_record) { MultisearchableModel.create!(:title => 'foning') }
|
1109
|
-
let(:query) { "Phoning" }
|
1110
|
-
it { is_expected.to include(soundalike_record) }
|
1111
|
-
end
|
1112
|
-
|
1113
|
-
context "with PgSearch.multisearch_options set to a Proc" do
|
1114
|
-
subject { PgSearch.multisearch(query, soundalike).map(&:searchable) }
|
1115
|
-
|
1116
|
-
before do
|
1117
|
-
allow(PgSearch).to receive(:multisearch_options) do
|
1118
|
-
lambda do |query, soundalike|
|
1119
|
-
if soundalike
|
1120
|
-
{:using => :dmetaphone, :query => query}
|
1121
|
-
else
|
1122
|
-
{:query => query}
|
1123
|
-
end
|
1124
|
-
end
|
1125
|
-
end
|
1126
|
-
end
|
1127
|
-
|
1128
|
-
with_model :MultisearchableModel do
|
1129
|
-
table do |t|
|
1130
|
-
t.string :title
|
1131
|
-
end
|
1132
|
-
model do
|
1133
|
-
include PgSearch
|
1134
|
-
multisearchable :against => :title
|
1135
|
-
end
|
1136
|
-
end
|
1137
|
-
|
1138
|
-
let!(:soundalike_record) { MultisearchableModel.create!(:title => 'foning') }
|
1139
|
-
let(:query) { "Phoning" }
|
1140
|
-
|
1141
|
-
context "with soundalike true" do
|
1142
|
-
let(:soundalike) { true }
|
1143
|
-
it { is_expected.to include(soundalike_record) }
|
1144
|
-
end
|
1145
|
-
|
1146
|
-
context "with soundalike false" do
|
1147
|
-
let(:soundalike) { false }
|
1148
|
-
it { is_expected.not_to include(soundalike_record) }
|
1149
|
-
end
|
1150
|
-
end
|
1151
|
-
|
1152
|
-
context "on an STI subclass" do
|
1153
|
-
with_model :SuperclassModel do
|
1154
|
-
table do |t|
|
1155
|
-
t.text 'content'
|
1156
|
-
t.string 'type'
|
1157
|
-
end
|
1158
|
-
end
|
1159
|
-
|
1160
|
-
before do
|
1161
|
-
searchable_subclass_model = Class.new(SuperclassModel) do
|
1162
|
-
include PgSearch
|
1163
|
-
multisearchable :against => :content
|
1164
|
-
end
|
1165
|
-
stub_const("SearchableSubclassModel", searchable_subclass_model)
|
1166
|
-
stub_const("AnotherSearchableSubclassModel", searchable_subclass_model)
|
1167
|
-
stub_const("NonSearchableSubclassModel", Class.new(SuperclassModel))
|
1168
|
-
end
|
1169
|
-
|
1170
|
-
it "returns only results for that subclass" do
|
1171
|
-
included = [
|
1172
|
-
SearchableSubclassModel.create!(:content => "foo bar")
|
1173
|
-
]
|
1174
|
-
excluded = [
|
1175
|
-
SearchableSubclassModel.create!(:content => "baz"),
|
1176
|
-
SuperclassModel.create!(:content => "foo bar"),
|
1177
|
-
SuperclassModel.create!(:content => "baz"),
|
1178
|
-
NonSearchableSubclassModel.create!(:content => "foo bar"),
|
1179
|
-
NonSearchableSubclassModel.create!(:content => "baz")
|
1180
|
-
]
|
1181
|
-
|
1182
|
-
expect(SuperclassModel.count).to be 6
|
1183
|
-
expect(SearchableSubclassModel.count).to be 2
|
1184
|
-
|
1185
|
-
expect(PgSearch::Document.count).to be 2
|
1186
|
-
|
1187
|
-
results = PgSearch.multisearch("foo bar")
|
1188
|
-
|
1189
|
-
expect(results.length).to be 1
|
1190
|
-
expect(results.first.searchable.class).to be SearchableSubclassModel
|
1191
|
-
expect(results.first.searchable).to eq included.first
|
1192
|
-
end
|
1193
|
-
|
1194
|
-
it "updates an existing STI model does not create a new pg_search document" do
|
1195
|
-
model = SearchableSubclassModel.create!(:content => "foo bar")
|
1196
|
-
expect(SearchableSubclassModel.count).to eq(1)
|
1197
|
-
# We fetch the model from the database again otherwise
|
1198
|
-
# the pg_search_document from the cache is used.
|
1199
|
-
model = SearchableSubclassModel.find(model.id)
|
1200
|
-
model.content = "foo"
|
1201
|
-
model.save!
|
1202
|
-
results = PgSearch.multisearch("foo")
|
1203
|
-
expect(results.size).to eq(SearchableSubclassModel.count)
|
1204
|
-
end
|
1205
|
-
|
1206
|
-
it "reindexing works" do
|
1207
|
-
NonSearchableSubclassModel.create!(:content => "foo bar")
|
1208
|
-
NonSearchableSubclassModel.create!(:content => "baz")
|
1209
|
-
expected = SearchableSubclassModel.create!(:content => "baz")
|
1210
|
-
SuperclassModel.create!(:content => "foo bar")
|
1211
|
-
SuperclassModel.create!(:content => "baz")
|
1212
|
-
SuperclassModel.create!(:content => "baz2")
|
1213
|
-
|
1214
|
-
expect(SuperclassModel.count).to be 6
|
1215
|
-
expect(NonSearchableSubclassModel.count).to be 2
|
1216
|
-
expect(SearchableSubclassModel.count).to be 1
|
1217
|
-
|
1218
|
-
expect(PgSearch::Document.count).to be 1
|
1219
|
-
|
1220
|
-
PgSearch::Multisearch.rebuild(SearchableSubclassModel)
|
1221
|
-
|
1222
|
-
expect(PgSearch::Document.count).to be 1
|
1223
|
-
expect(PgSearch::Document.first.searchable.class).to be SearchableSubclassModel
|
1224
|
-
expect(PgSearch::Document.first.searchable).to eq expected
|
1225
|
-
end
|
1226
|
-
|
1227
|
-
it "reindexing searchable STI doesn't clobber other related STI models" do
|
1228
|
-
searchable_s = SearchableSubclassModel.create!(:content => "baz")
|
1229
|
-
searchable_a = AnotherSearchableSubclassModel.create!(:content => "baz")
|
1230
|
-
|
1231
|
-
expect(PgSearch::Document.count).to be 2
|
1232
|
-
PgSearch::Multisearch.rebuild(SearchableSubclassModel)
|
1233
|
-
expect(PgSearch::Document.count).to be 2
|
1234
|
-
|
1235
|
-
classes = PgSearch::Document.all.collect {|d| d.searchable.class }
|
1236
|
-
expect(classes).to include SearchableSubclassModel
|
1237
|
-
expect(classes).to include AnotherSearchableSubclassModel
|
1238
|
-
end
|
1239
|
-
end
|
1240
|
-
end
|
1241
|
-
|
1242
|
-
describe ".disable_multisearch" do
|
1243
|
-
it "should temporarily disable multisearch" do
|
1244
|
-
@multisearch_enabled_before = PgSearch.multisearch_enabled?
|
1245
|
-
PgSearch.disable_multisearch do
|
1246
|
-
@multisearch_enabled_inside = PgSearch.multisearch_enabled?
|
1247
|
-
end
|
1248
|
-
@multisearch_enabled_after = PgSearch.multisearch_enabled?
|
1249
|
-
|
1250
|
-
expect(@multisearch_enabled_before).to be(true)
|
1251
|
-
expect(@multisearch_enabled_inside).to be(false)
|
1252
|
-
expect(@multisearch_enabled_after).to be(true)
|
1253
|
-
end
|
1254
|
-
|
1255
|
-
it "should reenable multisearch after an error" do
|
1256
|
-
@multisearch_enabled_before = PgSearch.multisearch_enabled?
|
1257
|
-
begin
|
1258
|
-
PgSearch.disable_multisearch do
|
1259
|
-
@multisearch_enabled_inside = PgSearch.multisearch_enabled?
|
1260
|
-
raise
|
1261
|
-
end
|
1262
|
-
rescue # rubocop:disable Lint/HandleExceptions
|
1263
|
-
end
|
1264
|
-
|
1265
|
-
@multisearch_enabled_after = PgSearch.multisearch_enabled?
|
1266
|
-
|
1267
|
-
expect(@multisearch_enabled_before).to be(true)
|
1268
|
-
expect(@multisearch_enabled_inside).to be(false)
|
1269
|
-
expect(@multisearch_enabled_after).to be(true)
|
1270
|
-
end
|
1271
|
-
|
1272
|
-
it "should not disable multisearch on other threads" do
|
1273
|
-
values = Queue.new
|
1274
|
-
sync = Queue.new
|
1275
|
-
Thread.new do
|
1276
|
-
values.push PgSearch.multisearch_enabled?
|
1277
|
-
sync.pop # wait
|
1278
|
-
values.push PgSearch.multisearch_enabled?
|
1279
|
-
sync.pop # wait
|
1280
|
-
values.push PgSearch.multisearch_enabled?
|
1281
|
-
end
|
1282
|
-
|
1283
|
-
@multisearch_enabled_before = values.pop
|
1284
|
-
PgSearch.disable_multisearch do
|
1285
|
-
sync.push :go
|
1286
|
-
@multisearch_enabled_inside = values.pop
|
1287
|
-
end
|
1288
|
-
sync.push :go
|
1289
|
-
@multisearch_enabled_after = values.pop
|
1290
|
-
|
1291
|
-
expect(@multisearch_enabled_before).to be(true)
|
1292
|
-
expect(@multisearch_enabled_inside).to be(true)
|
1293
|
-
expect(@multisearch_enabled_after).to be(true)
|
1294
|
-
end
|
1295
|
-
end
|
1296
1200
|
end
|
@@ -0,0 +1,221 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe PgSearch do
|
4
|
+
describe ".multisearch" do
|
5
|
+
with_table "pg_search_documents", {}, &DOCUMENTS_SCHEMA
|
6
|
+
|
7
|
+
describe "delegation to PgSearch::Document.search" do
|
8
|
+
subject { PgSearch.multisearch(query) }
|
9
|
+
|
10
|
+
let(:query) { double(:query) }
|
11
|
+
let(:relation) { double(:relation) }
|
12
|
+
before do
|
13
|
+
expect(PgSearch::Document).to receive(:search).with(query).and_return(relation)
|
14
|
+
end
|
15
|
+
|
16
|
+
it { is_expected.to eq(relation) }
|
17
|
+
end
|
18
|
+
|
19
|
+
context "with PgSearch.multisearch_options set to a Hash" do
|
20
|
+
before { allow(PgSearch).to receive(:multisearch_options).and_return({:using => :dmetaphone}) }
|
21
|
+
subject { PgSearch.multisearch(query).map(&:searchable) }
|
22
|
+
|
23
|
+
with_model :MultisearchableModel do
|
24
|
+
table do |t|
|
25
|
+
t.string :title
|
26
|
+
end
|
27
|
+
model do
|
28
|
+
include PgSearch
|
29
|
+
multisearchable :against => :title
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
let!(:soundalike_record) { MultisearchableModel.create!(:title => 'foning') }
|
34
|
+
let(:query) { "Phoning" }
|
35
|
+
it { is_expected.to include(soundalike_record) }
|
36
|
+
end
|
37
|
+
|
38
|
+
context "with PgSearch.multisearch_options set to a Proc" do
|
39
|
+
subject { PgSearch.multisearch(query, soundalike).map(&:searchable) }
|
40
|
+
|
41
|
+
before do
|
42
|
+
allow(PgSearch).to receive(:multisearch_options) do
|
43
|
+
lambda do |query, soundalike|
|
44
|
+
if soundalike
|
45
|
+
{:using => :dmetaphone, :query => query}
|
46
|
+
else
|
47
|
+
{:query => query}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
with_model :MultisearchableModel do
|
54
|
+
table do |t|
|
55
|
+
t.string :title
|
56
|
+
end
|
57
|
+
model do
|
58
|
+
include PgSearch
|
59
|
+
multisearchable :against => :title
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
let!(:soundalike_record) { MultisearchableModel.create!(:title => 'foning') }
|
64
|
+
let(:query) { "Phoning" }
|
65
|
+
|
66
|
+
context "with soundalike true" do
|
67
|
+
let(:soundalike) { true }
|
68
|
+
it { is_expected.to include(soundalike_record) }
|
69
|
+
end
|
70
|
+
|
71
|
+
context "with soundalike false" do
|
72
|
+
let(:soundalike) { false }
|
73
|
+
it { is_expected.not_to include(soundalike_record) }
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context "on an STI subclass" do
|
78
|
+
with_model :SuperclassModel do
|
79
|
+
table do |t|
|
80
|
+
t.text 'content'
|
81
|
+
t.string 'type'
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
before do
|
86
|
+
searchable_subclass_model = Class.new(SuperclassModel) do
|
87
|
+
include PgSearch
|
88
|
+
multisearchable :against => :content
|
89
|
+
end
|
90
|
+
stub_const("SearchableSubclassModel", searchable_subclass_model)
|
91
|
+
stub_const("AnotherSearchableSubclassModel", searchable_subclass_model)
|
92
|
+
stub_const("NonSearchableSubclassModel", Class.new(SuperclassModel))
|
93
|
+
end
|
94
|
+
|
95
|
+
it "returns only results for that subclass" do
|
96
|
+
included = [
|
97
|
+
SearchableSubclassModel.create!(:content => "foo bar")
|
98
|
+
]
|
99
|
+
excluded = [
|
100
|
+
SearchableSubclassModel.create!(:content => "baz"),
|
101
|
+
SuperclassModel.create!(:content => "foo bar"),
|
102
|
+
SuperclassModel.create!(:content => "baz"),
|
103
|
+
NonSearchableSubclassModel.create!(:content => "foo bar"),
|
104
|
+
NonSearchableSubclassModel.create!(:content => "baz")
|
105
|
+
]
|
106
|
+
|
107
|
+
expect(SuperclassModel.count).to be 6
|
108
|
+
expect(SearchableSubclassModel.count).to be 2
|
109
|
+
|
110
|
+
expect(PgSearch::Document.count).to be 2
|
111
|
+
|
112
|
+
results = PgSearch.multisearch("foo bar")
|
113
|
+
|
114
|
+
expect(results.length).to be 1
|
115
|
+
expect(results.first.searchable.class).to be SearchableSubclassModel
|
116
|
+
expect(results.first.searchable).to eq included.first
|
117
|
+
end
|
118
|
+
|
119
|
+
it "updates an existing STI model does not create a new pg_search document" do
|
120
|
+
model = SearchableSubclassModel.create!(:content => "foo bar")
|
121
|
+
expect(SearchableSubclassModel.count).to eq(1)
|
122
|
+
# We fetch the model from the database again otherwise
|
123
|
+
# the pg_search_document from the cache is used.
|
124
|
+
model = SearchableSubclassModel.find(model.id)
|
125
|
+
model.content = "foo"
|
126
|
+
model.save!
|
127
|
+
results = PgSearch.multisearch("foo")
|
128
|
+
expect(results.size).to eq(SearchableSubclassModel.count)
|
129
|
+
end
|
130
|
+
|
131
|
+
it "reindexing works" do
|
132
|
+
NonSearchableSubclassModel.create!(:content => "foo bar")
|
133
|
+
NonSearchableSubclassModel.create!(:content => "baz")
|
134
|
+
expected = SearchableSubclassModel.create!(:content => "baz")
|
135
|
+
SuperclassModel.create!(:content => "foo bar")
|
136
|
+
SuperclassModel.create!(:content => "baz")
|
137
|
+
SuperclassModel.create!(:content => "baz2")
|
138
|
+
|
139
|
+
expect(SuperclassModel.count).to be 6
|
140
|
+
expect(NonSearchableSubclassModel.count).to be 2
|
141
|
+
expect(SearchableSubclassModel.count).to be 1
|
142
|
+
|
143
|
+
expect(PgSearch::Document.count).to be 1
|
144
|
+
|
145
|
+
PgSearch::Multisearch.rebuild(SearchableSubclassModel)
|
146
|
+
|
147
|
+
expect(PgSearch::Document.count).to be 1
|
148
|
+
expect(PgSearch::Document.first.searchable.class).to be SearchableSubclassModel
|
149
|
+
expect(PgSearch::Document.first.searchable).to eq expected
|
150
|
+
end
|
151
|
+
|
152
|
+
it "reindexing searchable STI doesn't clobber other related STI models" do
|
153
|
+
searchable_s = SearchableSubclassModel.create!(:content => "baz")
|
154
|
+
searchable_a = AnotherSearchableSubclassModel.create!(:content => "baz")
|
155
|
+
|
156
|
+
expect(PgSearch::Document.count).to be 2
|
157
|
+
PgSearch::Multisearch.rebuild(SearchableSubclassModel)
|
158
|
+
expect(PgSearch::Document.count).to be 2
|
159
|
+
|
160
|
+
classes = PgSearch::Document.all.collect {|d| d.searchable.class }
|
161
|
+
expect(classes).to include SearchableSubclassModel
|
162
|
+
expect(classes).to include AnotherSearchableSubclassModel
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
describe ".disable_multisearch" do
|
168
|
+
it "should temporarily disable multisearch" do
|
169
|
+
@multisearch_enabled_before = PgSearch.multisearch_enabled?
|
170
|
+
PgSearch.disable_multisearch do
|
171
|
+
@multisearch_enabled_inside = PgSearch.multisearch_enabled?
|
172
|
+
end
|
173
|
+
@multisearch_enabled_after = PgSearch.multisearch_enabled?
|
174
|
+
|
175
|
+
expect(@multisearch_enabled_before).to be(true)
|
176
|
+
expect(@multisearch_enabled_inside).to be(false)
|
177
|
+
expect(@multisearch_enabled_after).to be(true)
|
178
|
+
end
|
179
|
+
|
180
|
+
it "should reenable multisearch after an error" do
|
181
|
+
@multisearch_enabled_before = PgSearch.multisearch_enabled?
|
182
|
+
begin
|
183
|
+
PgSearch.disable_multisearch do
|
184
|
+
@multisearch_enabled_inside = PgSearch.multisearch_enabled?
|
185
|
+
raise
|
186
|
+
end
|
187
|
+
rescue # rubocop:disable Lint/HandleExceptions
|
188
|
+
end
|
189
|
+
|
190
|
+
@multisearch_enabled_after = PgSearch.multisearch_enabled?
|
191
|
+
|
192
|
+
expect(@multisearch_enabled_before).to be(true)
|
193
|
+
expect(@multisearch_enabled_inside).to be(false)
|
194
|
+
expect(@multisearch_enabled_after).to be(true)
|
195
|
+
end
|
196
|
+
|
197
|
+
it "should not disable multisearch on other threads" do
|
198
|
+
values = Queue.new
|
199
|
+
sync = Queue.new
|
200
|
+
Thread.new do
|
201
|
+
values.push PgSearch.multisearch_enabled?
|
202
|
+
sync.pop # wait
|
203
|
+
values.push PgSearch.multisearch_enabled?
|
204
|
+
sync.pop # wait
|
205
|
+
values.push PgSearch.multisearch_enabled?
|
206
|
+
end
|
207
|
+
|
208
|
+
@multisearch_enabled_before = values.pop
|
209
|
+
PgSearch.disable_multisearch do
|
210
|
+
sync.push :go
|
211
|
+
@multisearch_enabled_inside = values.pop
|
212
|
+
end
|
213
|
+
sync.push :go
|
214
|
+
@multisearch_enabled_after = values.pop
|
215
|
+
|
216
|
+
expect(@multisearch_enabled_before).to be(true)
|
217
|
+
expect(@multisearch_enabled_inside).to be(true)
|
218
|
+
expect(@multisearch_enabled_after).to be(true)
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -15,7 +15,7 @@ require 'support/database'
|
|
15
15
|
require 'support/with_model'
|
16
16
|
|
17
17
|
DOCUMENTS_SCHEMA = lambda do |t|
|
18
|
-
t.belongs_to :searchable, :polymorphic => true
|
18
|
+
t.belongs_to :searchable, :polymorphic => true, :index => true
|
19
19
|
t.text :content
|
20
20
|
t.timestamps null: false
|
21
21
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pg_search
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Grant Hutchins
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-
|
12
|
+
date: 2015-04-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -115,14 +115,14 @@ dependencies:
|
|
115
115
|
requirements:
|
116
116
|
- - ">="
|
117
117
|
- !ruby/object:Gem::Version
|
118
|
-
version:
|
118
|
+
version: 0.30.0
|
119
119
|
type: :development
|
120
120
|
prerelease: false
|
121
121
|
version_requirements: !ruby/object:Gem::Requirement
|
122
122
|
requirements:
|
123
123
|
- - ">="
|
124
124
|
- !ruby/object:Gem::Version
|
125
|
-
version:
|
125
|
+
version: 0.30.0
|
126
126
|
description: PgSearch builds Active Record named scopes that take advantage of PostgreSQL's
|
127
127
|
full text search
|
128
128
|
email:
|
@@ -133,6 +133,7 @@ extensions: []
|
|
133
133
|
extra_rdoc_files: []
|
134
134
|
files:
|
135
135
|
- ".autotest"
|
136
|
+
- ".bundle/config"
|
136
137
|
- ".gitignore"
|
137
138
|
- ".rspec"
|
138
139
|
- ".rubocop.yml"
|
@@ -145,9 +146,6 @@ files:
|
|
145
146
|
- LICENSE
|
146
147
|
- README.md
|
147
148
|
- Rakefile
|
148
|
-
- bin/guard
|
149
|
-
- bin/rake
|
150
|
-
- bin/rspec
|
151
149
|
- lib/pg_search.rb
|
152
150
|
- lib/pg_search/compatibility.rb
|
153
151
|
- lib/pg_search/configuration.rb
|
@@ -191,6 +189,7 @@ files:
|
|
191
189
|
- spec/lib/pg_search/multisearch_spec.rb
|
192
190
|
- spec/lib/pg_search/multisearchable_spec.rb
|
193
191
|
- spec/lib/pg_search/normalizer_spec.rb
|
192
|
+
- spec/lib/pg_search_spec.rb
|
194
193
|
- spec/spec_helper.rb
|
195
194
|
- spec/support/database.rb
|
196
195
|
- spec/support/with_model.rb
|
@@ -240,6 +239,7 @@ test_files:
|
|
240
239
|
- spec/lib/pg_search/multisearch_spec.rb
|
241
240
|
- spec/lib/pg_search/multisearchable_spec.rb
|
242
241
|
- spec/lib/pg_search/normalizer_spec.rb
|
242
|
+
- spec/lib/pg_search_spec.rb
|
243
243
|
- spec/spec_helper.rb
|
244
244
|
- spec/support/database.rb
|
245
245
|
- spec/support/with_model.rb
|
data/bin/guard
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
#
|
3
|
-
# This file was generated by Bundler.
|
4
|
-
#
|
5
|
-
# The application 'guard' is installed as part of a gem, and
|
6
|
-
# this file is here to facilitate running it.
|
7
|
-
#
|
8
|
-
|
9
|
-
require 'pathname'
|
10
|
-
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
-
Pathname.new(__FILE__).realpath)
|
12
|
-
|
13
|
-
require 'rubygems'
|
14
|
-
require 'bundler/setup'
|
15
|
-
|
16
|
-
load Gem.bin_path('guard', 'guard')
|
data/bin/rake
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
#
|
3
|
-
# This file was generated by Bundler.
|
4
|
-
#
|
5
|
-
# The application 'rake' is installed as part of a gem, and
|
6
|
-
# this file is here to facilitate running it.
|
7
|
-
#
|
8
|
-
|
9
|
-
require 'pathname'
|
10
|
-
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
-
Pathname.new(__FILE__).realpath)
|
12
|
-
|
13
|
-
require 'rubygems'
|
14
|
-
require 'bundler/setup'
|
15
|
-
|
16
|
-
load Gem.bin_path('rake', 'rake')
|
data/bin/rspec
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
#
|
3
|
-
# This file was generated by Bundler.
|
4
|
-
#
|
5
|
-
# The application 'rspec' is installed as part of a gem, and
|
6
|
-
# this file is here to facilitate running it.
|
7
|
-
#
|
8
|
-
|
9
|
-
require 'pathname'
|
10
|
-
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
-
Pathname.new(__FILE__).realpath)
|
12
|
-
|
13
|
-
require 'rubygems'
|
14
|
-
require 'bundler/setup'
|
15
|
-
|
16
|
-
load Gem.bin_path('rspec-core', 'rspec')
|