pg_search 0.7.8 → 0.7.9
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/.rubocop.yml +8 -0
- data/.rubocop_todo.yml +273 -0
- data/.travis.yml +18 -6
- data/CHANGELOG.md +4 -0
- data/Gemfile +6 -4
- data/README.md +78 -17
- data/Rakefile +5 -8
- data/bin/rake +16 -0
- data/lib/pg_search/document.rb +4 -4
- data/lib/pg_search/features/tsearch.rb +15 -3
- data/lib/pg_search/multisearch.rb +1 -1
- data/lib/pg_search/multisearch/rebuilder.rb +19 -3
- data/lib/pg_search/multisearchable.rb +1 -4
- data/lib/pg_search/version.rb +1 -1
- data/pg_search.gemspec +4 -3
- data/spec/integration/pg_search_spec.rb +144 -22
- data/spec/lib/pg_search/features/tsearch_spec.rb +72 -0
- data/spec/lib/pg_search/multisearch/rebuilder_spec.rb +2 -2
- data/spec/lib/pg_search/multisearch_spec.rb +4 -4
- data/spec/spec_helper.rb +0 -1
- metadata +20 -5
- data/spec/support/coveralls.rb +0 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e2af7110ee0301accace6b1a5143605fdddaf59b
|
|
4
|
+
data.tar.gz: ae0a9e2e5da80e29afd0449057685d64f20cb08c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6d5b4e6084872eac490fa2e7e923a3c9e53bd5acf77596a6a2a42547ecf90cee8f75a9c1d9a5819bcf4bc3546fc2dcc8f1ba46848dd5561c62172235d8ffff6b
|
|
7
|
+
data.tar.gz: baf8e2bcf8fd110c8db6f1bd68acdb62af2510ec5eab40bfd607494f83c202282238db599b95c30e44b64d7a13338b894b2dd074d7104779512fd0efac7b5ad0
|
data/.rubocop.yml
ADDED
data/.rubocop_todo.yml
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
# This configuration was generated by `rubocop --auto-gen-config`
|
|
2
|
+
# on 2014-12-12 15:10:11 -0600 using RuboCop version 0.28.0.
|
|
3
|
+
# The point is for the user to remove these configuration records
|
|
4
|
+
# one by one as the offenses are removed from the code base.
|
|
5
|
+
# Note that changes in the inspected code, or installation of new
|
|
6
|
+
# versions of RuboCop, may require this file to be generated again.
|
|
7
|
+
|
|
8
|
+
# Offense count: 11
|
|
9
|
+
# Cop supports --auto-correct.
|
|
10
|
+
Lint/UnusedBlockArgument:
|
|
11
|
+
Enabled: false
|
|
12
|
+
|
|
13
|
+
# Offense count: 12
|
|
14
|
+
Lint/UselessAssignment:
|
|
15
|
+
Enabled: false
|
|
16
|
+
|
|
17
|
+
# Offense count: 6
|
|
18
|
+
Metrics/AbcSize:
|
|
19
|
+
Max: 27
|
|
20
|
+
|
|
21
|
+
# Offense count: 347
|
|
22
|
+
# Configuration parameters: AllowURI, URISchemes.
|
|
23
|
+
Metrics/LineLength:
|
|
24
|
+
Max: 304
|
|
25
|
+
|
|
26
|
+
# Offense count: 9
|
|
27
|
+
# Configuration parameters: CountComments.
|
|
28
|
+
Metrics/MethodLength:
|
|
29
|
+
Max: 21
|
|
30
|
+
|
|
31
|
+
# Offense count: 1
|
|
32
|
+
# Cop supports --auto-correct.
|
|
33
|
+
Style/Alias:
|
|
34
|
+
Enabled: false
|
|
35
|
+
|
|
36
|
+
# Offense count: 3
|
|
37
|
+
# Cop supports --auto-correct.
|
|
38
|
+
# Configuration parameters: EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle, SupportedLastArgumentHashStyles.
|
|
39
|
+
Style/AlignHash:
|
|
40
|
+
Enabled: false
|
|
41
|
+
|
|
42
|
+
# Offense count: 42
|
|
43
|
+
# Cop supports --auto-correct.
|
|
44
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
|
45
|
+
Style/AlignParameters:
|
|
46
|
+
Enabled: false
|
|
47
|
+
|
|
48
|
+
# Offense count: 14
|
|
49
|
+
# Cop supports --auto-correct.
|
|
50
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
|
51
|
+
Style/BarePercentLiterals:
|
|
52
|
+
Enabled: false
|
|
53
|
+
|
|
54
|
+
# Offense count: 1
|
|
55
|
+
# Cop supports --auto-correct.
|
|
56
|
+
Style/BlockEndNewline:
|
|
57
|
+
Enabled: false
|
|
58
|
+
|
|
59
|
+
# Offense count: 14
|
|
60
|
+
# Cop supports --auto-correct.
|
|
61
|
+
Style/Blocks:
|
|
62
|
+
Enabled: false
|
|
63
|
+
|
|
64
|
+
# Offense count: 1
|
|
65
|
+
# Cop supports --auto-correct.
|
|
66
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
|
67
|
+
Style/BracesAroundHashParameters:
|
|
68
|
+
Enabled: false
|
|
69
|
+
|
|
70
|
+
# Offense count: 27
|
|
71
|
+
Style/Documentation:
|
|
72
|
+
Enabled: false
|
|
73
|
+
|
|
74
|
+
# Offense count: 5
|
|
75
|
+
# Cop supports --auto-correct.
|
|
76
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
|
77
|
+
Style/DotPosition:
|
|
78
|
+
Enabled: false
|
|
79
|
+
|
|
80
|
+
# Offense count: 1
|
|
81
|
+
# Cop supports --auto-correct.
|
|
82
|
+
Style/ElseAlignment:
|
|
83
|
+
Enabled: false
|
|
84
|
+
|
|
85
|
+
# Offense count: 1
|
|
86
|
+
# Cop supports --auto-correct.
|
|
87
|
+
Style/EmptyLines:
|
|
88
|
+
Enabled: false
|
|
89
|
+
|
|
90
|
+
# Offense count: 6
|
|
91
|
+
# Cop supports --auto-correct.
|
|
92
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
|
93
|
+
Style/EmptyLinesAroundBlockBody:
|
|
94
|
+
Enabled: false
|
|
95
|
+
|
|
96
|
+
# Offense count: 2
|
|
97
|
+
# Cop supports --auto-correct.
|
|
98
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
|
99
|
+
Style/EmptyLinesAroundClassBody:
|
|
100
|
+
Enabled: false
|
|
101
|
+
|
|
102
|
+
# Offense count: 1
|
|
103
|
+
# Cop supports --auto-correct.
|
|
104
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
|
105
|
+
Style/EmptyLinesAroundModuleBody:
|
|
106
|
+
Enabled: false
|
|
107
|
+
|
|
108
|
+
# Offense count: 2
|
|
109
|
+
# Configuration parameters: MinBodyLength.
|
|
110
|
+
Style/GuardClause:
|
|
111
|
+
Enabled: false
|
|
112
|
+
|
|
113
|
+
# Offense count: 521
|
|
114
|
+
# Cop supports --auto-correct.
|
|
115
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
|
116
|
+
Style/HashSyntax:
|
|
117
|
+
Enabled: false
|
|
118
|
+
|
|
119
|
+
# Offense count: 1
|
|
120
|
+
# Configuration parameters: MaxLineLength.
|
|
121
|
+
Style/IfUnlessModifier:
|
|
122
|
+
Enabled: false
|
|
123
|
+
|
|
124
|
+
# Offense count: 23
|
|
125
|
+
# Cop supports --auto-correct.
|
|
126
|
+
Style/IndentArray:
|
|
127
|
+
Enabled: false
|
|
128
|
+
|
|
129
|
+
# Offense count: 1
|
|
130
|
+
# Cop supports --auto-correct.
|
|
131
|
+
Style/IndentationConsistency:
|
|
132
|
+
Enabled: false
|
|
133
|
+
|
|
134
|
+
# Offense count: 3
|
|
135
|
+
# Cop supports --auto-correct.
|
|
136
|
+
# Configuration parameters: Width.
|
|
137
|
+
Style/IndentationWidth:
|
|
138
|
+
Enabled: false
|
|
139
|
+
|
|
140
|
+
# Offense count: 10
|
|
141
|
+
Style/Lambda:
|
|
142
|
+
Enabled: false
|
|
143
|
+
|
|
144
|
+
# Offense count: 1
|
|
145
|
+
# Cop supports --auto-correct.
|
|
146
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
|
147
|
+
Style/MethodDefParentheses:
|
|
148
|
+
Enabled: false
|
|
149
|
+
|
|
150
|
+
# Offense count: 2
|
|
151
|
+
Style/MultilineBlockChain:
|
|
152
|
+
Enabled: false
|
|
153
|
+
|
|
154
|
+
# Offense count: 1
|
|
155
|
+
# Cop supports --auto-correct.
|
|
156
|
+
Style/MultilineBlockLayout:
|
|
157
|
+
Enabled: false
|
|
158
|
+
|
|
159
|
+
# Offense count: 16
|
|
160
|
+
# Cop supports --auto-correct.
|
|
161
|
+
Style/NumericLiterals:
|
|
162
|
+
MinDigits: 6
|
|
163
|
+
|
|
164
|
+
# Offense count: 12
|
|
165
|
+
# Cop supports --auto-correct.
|
|
166
|
+
# Configuration parameters: PreferredDelimiters.
|
|
167
|
+
Style/PercentLiteralDelimiters:
|
|
168
|
+
Enabled: false
|
|
169
|
+
|
|
170
|
+
# Offense count: 2
|
|
171
|
+
# Cop supports --auto-correct.
|
|
172
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
|
173
|
+
Style/PercentQLiterals:
|
|
174
|
+
Enabled: false
|
|
175
|
+
|
|
176
|
+
# Offense count: 1
|
|
177
|
+
# Cop supports --auto-correct.
|
|
178
|
+
Style/PerlBackrefs:
|
|
179
|
+
Enabled: false
|
|
180
|
+
|
|
181
|
+
# Offense count: 1
|
|
182
|
+
# Cop supports --auto-correct.
|
|
183
|
+
Style/Proc:
|
|
184
|
+
Enabled: false
|
|
185
|
+
|
|
186
|
+
# Offense count: 4
|
|
187
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
|
188
|
+
Style/RaiseArgs:
|
|
189
|
+
Enabled: false
|
|
190
|
+
|
|
191
|
+
# Offense count: 1
|
|
192
|
+
# Cop supports --auto-correct.
|
|
193
|
+
# Configuration parameters: AllowMultipleReturnValues.
|
|
194
|
+
Style/RedundantReturn:
|
|
195
|
+
Enabled: false
|
|
196
|
+
|
|
197
|
+
# Offense count: 2
|
|
198
|
+
Style/RegexpLiteral:
|
|
199
|
+
MaxSlashes: 0
|
|
200
|
+
|
|
201
|
+
# Offense count: 10
|
|
202
|
+
# Cop supports --auto-correct.
|
|
203
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
|
204
|
+
Style/SignalException:
|
|
205
|
+
Enabled: false
|
|
206
|
+
|
|
207
|
+
# Offense count: 2
|
|
208
|
+
# Cop supports --auto-correct.
|
|
209
|
+
Style/SpaceAfterComma:
|
|
210
|
+
Enabled: false
|
|
211
|
+
|
|
212
|
+
# Offense count: 1
|
|
213
|
+
# Cop supports --auto-correct.
|
|
214
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
|
215
|
+
Style/SpaceAroundEqualsInParameterDefault:
|
|
216
|
+
Enabled: false
|
|
217
|
+
|
|
218
|
+
# Offense count: 1
|
|
219
|
+
# Cop supports --auto-correct.
|
|
220
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
|
221
|
+
Style/SpaceBeforeBlockBraces:
|
|
222
|
+
Enabled: false
|
|
223
|
+
|
|
224
|
+
# Offense count: 2
|
|
225
|
+
# Cop supports --auto-correct.
|
|
226
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles, EnforcedStyleForEmptyBraces, SpaceBeforeBlockParameters.
|
|
227
|
+
Style/SpaceInsideBlockBraces:
|
|
228
|
+
Enabled: false
|
|
229
|
+
|
|
230
|
+
# Offense count: 76
|
|
231
|
+
# Cop supports --auto-correct.
|
|
232
|
+
# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces, SupportedStyles.
|
|
233
|
+
Style/SpaceInsideHashLiteralBraces:
|
|
234
|
+
Enabled: false
|
|
235
|
+
|
|
236
|
+
# Offense count: 2
|
|
237
|
+
# Cop supports --auto-correct.
|
|
238
|
+
Style/SpaceInsideParens:
|
|
239
|
+
Enabled: false
|
|
240
|
+
|
|
241
|
+
# Offense count: 3
|
|
242
|
+
# Cop supports --auto-correct.
|
|
243
|
+
Style/SpecialGlobalVars:
|
|
244
|
+
Enabled: false
|
|
245
|
+
|
|
246
|
+
# Offense count: 2
|
|
247
|
+
# Cop supports --auto-correct.
|
|
248
|
+
# Configuration parameters: IgnoredMethods.
|
|
249
|
+
Style/SymbolProc:
|
|
250
|
+
Enabled: false
|
|
251
|
+
|
|
252
|
+
# Offense count: 4
|
|
253
|
+
# Cop supports --auto-correct.
|
|
254
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
|
255
|
+
Style/TrailingBlankLines:
|
|
256
|
+
Enabled: false
|
|
257
|
+
|
|
258
|
+
# Offense count: 9
|
|
259
|
+
# Cop supports --auto-correct.
|
|
260
|
+
# Configuration parameters: EnforcedStyleForMultiline, SupportedStyles.
|
|
261
|
+
Style/TrailingComma:
|
|
262
|
+
Enabled: false
|
|
263
|
+
|
|
264
|
+
# Offense count: 6
|
|
265
|
+
# Cop supports --auto-correct.
|
|
266
|
+
Style/UnneededPercentQ:
|
|
267
|
+
Enabled: false
|
|
268
|
+
|
|
269
|
+
# Offense count: 3
|
|
270
|
+
# Cop supports --auto-correct.
|
|
271
|
+
# Configuration parameters: WordRegex.
|
|
272
|
+
Style/WordArray:
|
|
273
|
+
MinSize: 2
|
data/.travis.yml
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
language: ruby
|
|
2
|
+
sudo: false
|
|
2
3
|
|
|
3
4
|
rvm:
|
|
4
|
-
- 1.9
|
|
5
|
-
- 2.0
|
|
6
|
-
- 2.1
|
|
5
|
+
- "1.9"
|
|
6
|
+
- "2.0"
|
|
7
|
+
- "2.1"
|
|
8
|
+
- "2.2"
|
|
7
9
|
- jruby-19mode
|
|
8
10
|
|
|
9
11
|
env:
|
|
10
12
|
- ACTIVE_RECORD_BRANCH="master"
|
|
13
|
+
- ACTIVE_RECORD_BRANCH="4-2-stable"
|
|
11
14
|
- ACTIVE_RECORD_BRANCH="4-1-stable"
|
|
12
15
|
- ACTIVE_RECORD_BRANCH="4-0-stable"
|
|
13
|
-
- ACTIVE_RECORD_VERSION="~> 4.2.0
|
|
16
|
+
- ACTIVE_RECORD_VERSION="~> 4.2.0"
|
|
14
17
|
- ACTIVE_RECORD_VERSION="~> 4.1.0"
|
|
15
18
|
- ACTIVE_RECORD_VERSION="~> 4.0.0"
|
|
16
19
|
- ACTIVE_RECORD_VERSION="~> 3.2.0"
|
|
@@ -20,11 +23,20 @@ matrix:
|
|
|
20
23
|
allow_failures:
|
|
21
24
|
- rvm: jruby-19mode
|
|
22
25
|
- env: ACTIVE_RECORD_BRANCH="master"
|
|
26
|
+
- env: ACTIVE_RECORD_BRANCH="4-2-stable"
|
|
23
27
|
- env: ACTIVE_RECORD_BRANCH="4-1-stable"
|
|
24
28
|
- env: ACTIVE_RECORD_BRANCH="4-0-stable"
|
|
25
|
-
|
|
29
|
+
exclude:
|
|
30
|
+
- rvm: "1.9"
|
|
31
|
+
env: ACTIVE_RECORD_BRANCH="master"
|
|
32
|
+
- rvm: "2.0"
|
|
33
|
+
env: ACTIVE_RECORD_BRANCH="master"
|
|
34
|
+
- rvm: "2.1"
|
|
35
|
+
env: ACTIVE_RECORD_BRANCH="master"
|
|
36
|
+
- rvm: jruby-19mode
|
|
37
|
+
env: ACTIVE_RECORD_BRANCH="master"
|
|
26
38
|
|
|
27
39
|
before_script:
|
|
28
40
|
- "psql -c 'create database pg_search_test;' -U postgres >/dev/null"
|
|
29
41
|
|
|
30
|
-
script: "
|
|
42
|
+
script: "bin/rake"
|
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
|
@@ -5,11 +5,13 @@ gemspec
|
|
|
5
5
|
gem 'pg', :platform => :ruby
|
|
6
6
|
gem "activerecord-jdbcpostgresql-adapter", ">= 1.3.1", :platform => :jruby
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
gem
|
|
8
|
+
if ENV['ACTIVE_RECORD_BRANCH']
|
|
9
|
+
gem 'activerecord', :git => 'https://github.com/rails/rails.git', :branch => ENV['ACTIVE_RECORD_BRANCH']
|
|
10
|
+
gem 'arel', :git => 'https://github.com/rails/arel.git' if ENV['ACTIVE_RECORD_BRANCH'] == 'master'
|
|
11
|
+
end
|
|
10
12
|
|
|
11
|
-
if ENV[
|
|
12
|
-
gem '
|
|
13
|
+
if ENV['ACTIVE_RECORD_VERSION']
|
|
14
|
+
gem 'activerecord', ENV['ACTIVE_RECORD_VERSION']
|
|
13
15
|
end
|
|
14
16
|
|
|
15
17
|
group :development do
|
data/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# [pg_search](http://github.com/Casecommons/pg_search/)
|
|
2
2
|
|
|
3
3
|
[](https://travis-ci.org/Casecommons/pg_search)
|
|
4
|
-
[](https://codeclimate.com/github/Casecommons/pg_search)
|
|
5
|
-
[](https://codeclimate.com/github/Casecommons/pg_search)
|
|
5
|
+
[](https://rubygems.org/gems/pg_search)
|
|
6
|
+
[](https://gemnasium.com/Casecommons/pg_search)
|
|
7
|
+
[](http://inch-ci.org/github/Casecommons/pg_search)
|
|
8
8
|
|
|
9
9
|
## DESCRIPTION
|
|
10
10
|
|
|
@@ -562,6 +562,36 @@ robin = Superhero.create :name => 'Robin'
|
|
|
562
562
|
|
|
563
563
|
Superhero.whose_name_starts_with("Bat") # => [batman, batgirl]
|
|
564
564
|
```
|
|
565
|
+
##### :negation
|
|
566
|
+
|
|
567
|
+
PostgreSQL's full text search matches all search terms by default. If you want
|
|
568
|
+
to exclude certain words, you can set :negation to true. Then any term that begins with
|
|
569
|
+
an exclamation point `!` will be excluded from the results. Since this
|
|
570
|
+
is a :tsearch-specific option, you should pass it to :tsearch directly, as
|
|
571
|
+
shown in the following example.
|
|
572
|
+
|
|
573
|
+
Note that combining this with other search features can have unexpected results. For
|
|
574
|
+
example, :trigram searches don't have a concept of excluded terms, and thus if you
|
|
575
|
+
use both :tsearch and :trigram in tandem, you may still find results that contain the
|
|
576
|
+
term that you were trying to exclude.
|
|
577
|
+
|
|
578
|
+
```ruby
|
|
579
|
+
class Animal < ActiveRecord::Base
|
|
580
|
+
include PgSearch
|
|
581
|
+
pg_search_scope :with_name_matching,
|
|
582
|
+
:against => :name,
|
|
583
|
+
:using => {
|
|
584
|
+
:tsearch => {:negation => true}
|
|
585
|
+
}
|
|
586
|
+
end
|
|
587
|
+
|
|
588
|
+
one_fish = Animal.create(:name => "one fish")
|
|
589
|
+
two_fish = Animal.create(:name => "two fish")
|
|
590
|
+
red_fish = Animal.create(:name => "red fish")
|
|
591
|
+
blue_fish = Animal.create(:name => "blue fish")
|
|
592
|
+
|
|
593
|
+
Animal.with_name_matching("fish !red !blue") # => [one_fish, two_fish]
|
|
594
|
+
```
|
|
565
595
|
|
|
566
596
|
##### :dictionary
|
|
567
597
|
|
|
@@ -879,19 +909,20 @@ To use this functionality you'll need to do a few things:
|
|
|
879
909
|
function uses.
|
|
880
910
|
* Add the option to pg_search_scope, e.g:
|
|
881
911
|
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
912
|
+
```ruby
|
|
913
|
+
pg_search_scope :fast_content_search,
|
|
914
|
+
:against => :content,
|
|
915
|
+
:using => {
|
|
916
|
+
dmetaphone: {
|
|
917
|
+
tsvector_column: 'tsvector_content_dmetaphone'
|
|
918
|
+
},
|
|
919
|
+
tsearch: {
|
|
920
|
+
dictionary: 'english',
|
|
921
|
+
tsvector_column: 'tsvector_content_tsearch'
|
|
922
|
+
}
|
|
923
|
+
trigram: {} # trigram does not use tsvectors
|
|
924
|
+
}
|
|
925
|
+
```
|
|
895
926
|
* You cannot dump a `tsvector` column to `schema.rb`. Instead, you need to switch to using the native PostgreSQL SQL format schema dump.
|
|
896
927
|
In your `config/application.rb` you should set
|
|
897
928
|
|
|
@@ -903,6 +934,36 @@ To use this functionality you'll need to do a few things:
|
|
|
903
934
|
Please note that the :against column is only used when the tsvector_column is
|
|
904
935
|
not present for the search type.
|
|
905
936
|
|
|
937
|
+
#### Combining multiple tsvectors
|
|
938
|
+
|
|
939
|
+
It's possible to search against more than one tsvector at a time. This could be useful if you want to maintain multiple search scopes but do not want to maintain separate tsvectors for each scope. For example:
|
|
940
|
+
|
|
941
|
+
```ruby
|
|
942
|
+
pg_search_scope :search_title,
|
|
943
|
+
:against => :title,
|
|
944
|
+
:using => {
|
|
945
|
+
:tsearch => {
|
|
946
|
+
:tsvector_column => "title_tsvector"
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
pg_search_scope :search_body,
|
|
951
|
+
:against => :body,
|
|
952
|
+
:using => {
|
|
953
|
+
:tsearch => {
|
|
954
|
+
:tsvector_column => "body_tsvector"
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
pg_search_scope :search_title_and_body,
|
|
959
|
+
:against => [:title, :body],
|
|
960
|
+
:using => {
|
|
961
|
+
:tsearch => {
|
|
962
|
+
:tsvector_column => ["title_tsvector", "body_tsvector"]
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
```
|
|
966
|
+
|
|
906
967
|
### Configuring ranking and ordering
|
|
907
968
|
|
|
908
969
|
#### :ranked_by (Choosing a ranking algorithm)
|
data/Rakefile
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
require 'bundler'
|
|
2
2
|
Bundler::GemHelper.install_tasks
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
require 'rspec/core/rake_task'
|
|
5
|
+
RSpec::Core::RakeTask.new(:spec)
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
end
|
|
7
|
+
require "rubocop/rake_task"
|
|
8
|
+
RuboCop::RakeTask.new
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
task "spec" do
|
|
12
|
-
bundle_exec("rspec spec")
|
|
13
|
-
end
|
|
10
|
+
task :default => %w[ spec rubocop ]
|
data/bin/rake
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
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/lib/pg_search/document.rb
CHANGED
|
@@ -18,10 +18,10 @@ module PgSearch
|
|
|
18
18
|
|
|
19
19
|
pg_search_scope :search, lambda { |*args|
|
|
20
20
|
options = if PgSearch.multisearch_options.respond_to?(:call)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
PgSearch.multisearch_options.call(*args)
|
|
22
|
+
else
|
|
23
|
+
{:query => args.first}.merge(PgSearch.multisearch_options)
|
|
24
|
+
end
|
|
25
25
|
|
|
26
26
|
{:against => :content}.merge(options)
|
|
27
27
|
}
|
|
@@ -29,13 +29,20 @@ module PgSearch
|
|
|
29
29
|
DISALLOWED_TSQUERY_CHARACTERS = /['?\\:]/
|
|
30
30
|
|
|
31
31
|
def tsquery_for_term(unsanitized_term)
|
|
32
|
+
if options[:negation] && unsanitized_term.start_with?("!")
|
|
33
|
+
unsanitized_term[0] = ''
|
|
34
|
+
negated = true
|
|
35
|
+
end
|
|
36
|
+
|
|
32
37
|
sanitized_term = unsanitized_term.gsub(DISALLOWED_TSQUERY_CHARACTERS, " ")
|
|
33
38
|
|
|
34
39
|
term_sql = Arel.sql(normalize(connection.quote(sanitized_term)))
|
|
35
40
|
|
|
36
41
|
# After this, the SQL expression evaluates to a string containing the term surrounded by single-quotes.
|
|
37
|
-
# If :prefix is true, then the term will
|
|
42
|
+
# If :prefix is true, then the term will have :* appended to the end.
|
|
43
|
+
# If :negated is true, then the term will have ! prepended to the front.
|
|
38
44
|
terms = [
|
|
45
|
+
(Compatibility.build_quoted('!') if negated),
|
|
39
46
|
Compatibility.build_quoted("' "),
|
|
40
47
|
term_sql,
|
|
41
48
|
Compatibility.build_quoted(" '"),
|
|
@@ -65,8 +72,13 @@ module PgSearch
|
|
|
65
72
|
end
|
|
66
73
|
|
|
67
74
|
if options[:tsvector_column]
|
|
68
|
-
|
|
69
|
-
|
|
75
|
+
tsvector_columns = Array.wrap(options[:tsvector_column])
|
|
76
|
+
|
|
77
|
+
tsdocument_terms << tsvector_columns.map do |tsvector_column|
|
|
78
|
+
column_name = connection.quote_column_name(tsvector_column)
|
|
79
|
+
|
|
80
|
+
"#{quoted_table_name}.#{column_name}"
|
|
81
|
+
end
|
|
70
82
|
end
|
|
71
83
|
|
|
72
84
|
tsdocument_terms.join(' || ')
|
|
@@ -6,7 +6,7 @@ module PgSearch
|
|
|
6
6
|
class << self
|
|
7
7
|
def rebuild(model, clean_up=true)
|
|
8
8
|
model.transaction do
|
|
9
|
-
PgSearch::Document.where(:searchable_type => model.name).delete_all if clean_up
|
|
9
|
+
PgSearch::Document.where(:searchable_type => model.base_class.name).delete_all if clean_up
|
|
10
10
|
Rebuilder.new(model).rebuild
|
|
11
11
|
end
|
|
12
12
|
end
|
|
@@ -35,14 +35,14 @@ module PgSearch
|
|
|
35
35
|
def rebuild_sql_template
|
|
36
36
|
<<-SQL.strip_heredoc
|
|
37
37
|
INSERT INTO :documents_table (searchable_type, searchable_id, content, created_at, updated_at)
|
|
38
|
-
SELECT :
|
|
38
|
+
SELECT :base_model_name AS searchable_type,
|
|
39
39
|
:model_table.#{primary_key} AS searchable_id,
|
|
40
40
|
(
|
|
41
41
|
:content_expressions
|
|
42
42
|
) AS content,
|
|
43
43
|
:current_time AS created_at,
|
|
44
44
|
:current_time AS updated_at
|
|
45
|
-
FROM :model_table
|
|
45
|
+
FROM :model_table :sti_clause
|
|
46
46
|
SQL
|
|
47
47
|
end
|
|
48
48
|
|
|
@@ -52,8 +52,20 @@ module PgSearch
|
|
|
52
52
|
end
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
+
def sti_clause
|
|
56
|
+
clause = ""
|
|
57
|
+
if model.column_names.include? 'type'
|
|
58
|
+
clause = "WHERE"
|
|
59
|
+
if model.base_class == model
|
|
60
|
+
clause = "#{clause} type IS NULL OR"
|
|
61
|
+
end
|
|
62
|
+
clause = "#{clause} type = #{model_name}"
|
|
63
|
+
end
|
|
64
|
+
clause
|
|
65
|
+
end
|
|
66
|
+
|
|
55
67
|
def replacements
|
|
56
|
-
%w[content_expressions model_name model_table documents_table current_time]
|
|
68
|
+
%w[content_expressions base_model_name model_name model_table documents_table current_time sti_clause]
|
|
57
69
|
end
|
|
58
70
|
|
|
59
71
|
def content_expressions
|
|
@@ -70,6 +82,10 @@ module PgSearch
|
|
|
70
82
|
connection.quote(model.name)
|
|
71
83
|
end
|
|
72
84
|
|
|
85
|
+
def base_model_name
|
|
86
|
+
connection.quote(model.base_class.name)
|
|
87
|
+
end
|
|
88
|
+
|
|
73
89
|
def model_table
|
|
74
90
|
model.quoted_table_name
|
|
75
91
|
end
|
|
@@ -23,10 +23,7 @@ module PgSearch
|
|
|
23
23
|
unless_conditions.all? { |condition| !condition.to_proc.call(self) }
|
|
24
24
|
|
|
25
25
|
if should_have_document
|
|
26
|
-
|
|
27
|
-
build_pg_search_document.searchable_type = self.class.name
|
|
28
|
-
end
|
|
29
|
-
pg_search_document.save
|
|
26
|
+
pg_search_document ? pg_search_document.save : create_pg_search_document
|
|
30
27
|
else
|
|
31
28
|
pg_search_document.destroy if pg_search_document
|
|
32
29
|
end
|
data/lib/pg_search/version.rb
CHANGED
data/pg_search.gemspec
CHANGED
|
@@ -17,14 +17,15 @@ Gem::Specification.new do |s|
|
|
|
17
17
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
18
18
|
s.require_paths = ["lib"]
|
|
19
19
|
|
|
20
|
-
s.add_dependency 'activerecord', '>=3.1'
|
|
21
|
-
s.add_dependency 'activesupport', '>=3.1'
|
|
20
|
+
s.add_dependency 'activerecord', '>= 3.1'
|
|
21
|
+
s.add_dependency 'activesupport', '>= 3.1'
|
|
22
22
|
s.add_dependency 'arel'
|
|
23
23
|
|
|
24
24
|
s.add_development_dependency 'rake'
|
|
25
25
|
s.add_development_dependency 'pry'
|
|
26
26
|
s.add_development_dependency 'rspec', '~> 3.0'
|
|
27
|
-
s.add_development_dependency 'with_model'
|
|
27
|
+
s.add_development_dependency 'with_model', '>= 1.2'
|
|
28
|
+
s.add_development_dependency 'rubocop'
|
|
28
29
|
|
|
29
30
|
s.required_ruby_version = ">= 1.9.2"
|
|
30
31
|
end
|
|
@@ -536,6 +536,58 @@ describe "an Active Record model which includes PgSearch" do
|
|
|
536
536
|
expect(results.map(&:title)).to eq([])
|
|
537
537
|
end
|
|
538
538
|
end
|
|
539
|
+
|
|
540
|
+
context "with :negation" do
|
|
541
|
+
before do
|
|
542
|
+
ModelWithPgSearch.pg_search_scope :search_with_negation,
|
|
543
|
+
:against => :title,
|
|
544
|
+
:using => {
|
|
545
|
+
:tsearch => {:negation => true}
|
|
546
|
+
}
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
it "doesn't return results that contain terms prepended with '!'" do
|
|
550
|
+
included = [
|
|
551
|
+
ModelWithPgSearch.create!(:title => "one fish"),
|
|
552
|
+
ModelWithPgSearch.create!(:title => "two fish")
|
|
553
|
+
]
|
|
554
|
+
|
|
555
|
+
excluded = [
|
|
556
|
+
ModelWithPgSearch.create!(:title => "red fish"),
|
|
557
|
+
ModelWithPgSearch.create!(:title => "blue fish")
|
|
558
|
+
]
|
|
559
|
+
|
|
560
|
+
results = ModelWithPgSearch.search_with_negation("fish !red !blue")
|
|
561
|
+
|
|
562
|
+
expect(results).to include(*included)
|
|
563
|
+
expect(results).not_to include(*excluded)
|
|
564
|
+
end
|
|
565
|
+
end
|
|
566
|
+
|
|
567
|
+
context "without :negation" do
|
|
568
|
+
before do
|
|
569
|
+
ModelWithPgSearch.pg_search_scope :search_without_negation,
|
|
570
|
+
:against => :title,
|
|
571
|
+
:using => {
|
|
572
|
+
:tsearch => {}
|
|
573
|
+
}
|
|
574
|
+
end
|
|
575
|
+
|
|
576
|
+
it "return results that contain terms prepended with '!'" do
|
|
577
|
+
included = [
|
|
578
|
+
ModelWithPgSearch.create!(:title => "!bang")
|
|
579
|
+
]
|
|
580
|
+
|
|
581
|
+
excluded = [
|
|
582
|
+
ModelWithPgSearch.create!(:title => "?question")
|
|
583
|
+
]
|
|
584
|
+
|
|
585
|
+
results = ModelWithPgSearch.search_without_negation("!bang")
|
|
586
|
+
|
|
587
|
+
expect(results).to include(*included)
|
|
588
|
+
expect(results).not_to include(*excluded)
|
|
589
|
+
end
|
|
590
|
+
end
|
|
539
591
|
end
|
|
540
592
|
|
|
541
593
|
context "using dmetaphone" do
|
|
@@ -735,6 +787,30 @@ describe "an Active Record model which includes PgSearch" do
|
|
|
735
787
|
end
|
|
736
788
|
end
|
|
737
789
|
|
|
790
|
+
context 'using multiple tsvector columns' do
|
|
791
|
+
with_model :ModelWithTsvector do
|
|
792
|
+
model do
|
|
793
|
+
include PgSearch
|
|
794
|
+
|
|
795
|
+
pg_search_scope :search_by_multiple_tsvector_columns,
|
|
796
|
+
:against => ['content', 'message'],
|
|
797
|
+
:using => {
|
|
798
|
+
:tsearch => {
|
|
799
|
+
:tsvector_column => ['content_tsvector', 'message_tsvector'],
|
|
800
|
+
:dictionary => 'english'
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
end
|
|
804
|
+
end
|
|
805
|
+
|
|
806
|
+
it 'concats tsvector columns' do
|
|
807
|
+
expected = "#{ModelWithTsvector.quoted_table_name}.\"content_tsvector\" || "\
|
|
808
|
+
"#{ModelWithTsvector.quoted_table_name}.\"message_tsvector\""
|
|
809
|
+
|
|
810
|
+
expect(ModelWithTsvector.search_by_multiple_tsvector_columns("something").to_sql).to include(expected)
|
|
811
|
+
end
|
|
812
|
+
end
|
|
813
|
+
|
|
738
814
|
context "using a tsvector column with" do
|
|
739
815
|
with_model :ModelWithTsvector do
|
|
740
816
|
table do |t|
|
|
@@ -937,29 +1013,29 @@ describe "an Active Record model which includes PgSearch" do
|
|
|
937
1013
|
before do
|
|
938
1014
|
SuperclassModel.pg_search_scope :search_content, :against => :content
|
|
939
1015
|
|
|
940
|
-
class
|
|
1016
|
+
class SearchableSubclassModel < SuperclassModel
|
|
941
1017
|
end
|
|
942
1018
|
|
|
943
|
-
class
|
|
1019
|
+
class AnotherSearchableSubclassModel < SuperclassModel
|
|
944
1020
|
end
|
|
945
1021
|
end
|
|
946
1022
|
|
|
947
1023
|
it "returns only results for that subclass" do
|
|
948
1024
|
included = [
|
|
949
|
-
|
|
1025
|
+
SearchableSubclassModel.create!(:content => "foo bar")
|
|
950
1026
|
]
|
|
951
1027
|
excluded = [
|
|
952
|
-
|
|
1028
|
+
SearchableSubclassModel.create!(:content => "baz"),
|
|
953
1029
|
SuperclassModel.create!(:content => "foo bar"),
|
|
954
1030
|
SuperclassModel.create!(:content => "baz"),
|
|
955
|
-
|
|
956
|
-
|
|
1031
|
+
AnotherSearchableSubclassModel.create!(:content => "foo bar"),
|
|
1032
|
+
AnotherSearchableSubclassModel.create!(:content => "baz")
|
|
957
1033
|
]
|
|
958
1034
|
|
|
959
1035
|
expect(SuperclassModel.count).to eq(6)
|
|
960
|
-
expect(
|
|
1036
|
+
expect(SearchableSubclassModel.count).to eq(2)
|
|
961
1037
|
|
|
962
|
-
results =
|
|
1038
|
+
results = SearchableSubclassModel.search_content("foo bar")
|
|
963
1039
|
|
|
964
1040
|
expect(results).to include(*included)
|
|
965
1041
|
expect(results).not_to include(*excluded)
|
|
@@ -1074,7 +1150,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
|
1074
1150
|
end
|
|
1075
1151
|
|
|
1076
1152
|
context "on an STI subclass" do
|
|
1077
|
-
with_model :
|
|
1153
|
+
with_model :SuperclassModel do
|
|
1078
1154
|
table do |t|
|
|
1079
1155
|
t.text 'content'
|
|
1080
1156
|
t.string 'type'
|
|
@@ -1082,14 +1158,13 @@ describe "an Active Record model which includes PgSearch" do
|
|
|
1082
1158
|
end
|
|
1083
1159
|
|
|
1084
1160
|
before do
|
|
1085
|
-
|
|
1086
|
-
class SearchableSubclassModel < ASuperclassModel
|
|
1161
|
+
searchable_subclass_model = Class.new(SuperclassModel) do
|
|
1087
1162
|
include PgSearch
|
|
1088
1163
|
multisearchable :against => :content
|
|
1089
1164
|
end
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1165
|
+
stub_const("SearchableSubclassModel", searchable_subclass_model)
|
|
1166
|
+
stub_const("AnotherSearchableSubclassModel", searchable_subclass_model)
|
|
1167
|
+
stub_const("NonSearchableSubclassModel", Class.new(SuperclassModel))
|
|
1093
1168
|
end
|
|
1094
1169
|
|
|
1095
1170
|
it "returns only results for that subclass" do
|
|
@@ -1098,21 +1173,68 @@ describe "an Active Record model which includes PgSearch" do
|
|
|
1098
1173
|
]
|
|
1099
1174
|
excluded = [
|
|
1100
1175
|
SearchableSubclassModel.create!(:content => "baz"),
|
|
1101
|
-
|
|
1102
|
-
|
|
1176
|
+
SuperclassModel.create!(:content => "foo bar"),
|
|
1177
|
+
SuperclassModel.create!(:content => "baz"),
|
|
1103
1178
|
NonSearchableSubclassModel.create!(:content => "foo bar"),
|
|
1104
1179
|
NonSearchableSubclassModel.create!(:content => "baz")
|
|
1105
1180
|
]
|
|
1106
1181
|
|
|
1107
|
-
expect(
|
|
1182
|
+
expect(SuperclassModel.count).to be 6
|
|
1108
1183
|
expect(SearchableSubclassModel.count).to be 2
|
|
1109
1184
|
|
|
1185
|
+
expect(PgSearch::Document.count).to be 2
|
|
1186
|
+
|
|
1110
1187
|
results = PgSearch.multisearch("foo bar")
|
|
1111
1188
|
|
|
1112
|
-
expect(results.
|
|
1113
|
-
expect(results.
|
|
1114
|
-
expect(results.
|
|
1115
|
-
|
|
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
|
|
1116
1238
|
end
|
|
1117
1239
|
end
|
|
1118
1240
|
end
|
|
@@ -1137,7 +1259,7 @@ describe "an Active Record model which includes PgSearch" do
|
|
|
1137
1259
|
@multisearch_enabled_inside = PgSearch.multisearch_enabled?
|
|
1138
1260
|
raise
|
|
1139
1261
|
end
|
|
1140
|
-
rescue
|
|
1262
|
+
rescue # rubocop:disable Lint/HandleExceptions
|
|
1141
1263
|
end
|
|
1142
1264
|
|
|
1143
1265
|
@multisearch_enabled_after = PgSearch.multisearch_enabled?
|
|
@@ -49,5 +49,77 @@ describe PgSearch::Features::TSearch do
|
|
|
49
49
|
%Q{((to_tsvector('simple', coalesce(#{Model.quoted_table_name}."name"::text, '')) || to_tsvector('simple', coalesce(#{Model.quoted_table_name}."content"::text, ''))) @@ (to_tsquery('simple', ''' ' || 'query' || ' ''')))}
|
|
50
50
|
)
|
|
51
51
|
end
|
|
52
|
+
|
|
53
|
+
context "when options[:negation] is true" do
|
|
54
|
+
it "returns a negated expression when a query is prepended with !" do
|
|
55
|
+
query = "!query"
|
|
56
|
+
columns = [
|
|
57
|
+
PgSearch::Configuration::Column.new(:name, nil, Model),
|
|
58
|
+
PgSearch::Configuration::Column.new(:content, nil, Model),
|
|
59
|
+
]
|
|
60
|
+
options = {:negation => true}
|
|
61
|
+
config = double(:config, :ignore => [])
|
|
62
|
+
normalizer = PgSearch::Normalizer.new(config)
|
|
63
|
+
|
|
64
|
+
feature = described_class.new(query, options, columns, Model, normalizer)
|
|
65
|
+
expect(feature.conditions.to_sql).to eq(
|
|
66
|
+
%Q{((to_tsvector('simple', coalesce(#{Model.quoted_table_name}."name"::text, '')) || to_tsvector('simple', coalesce(#{Model.quoted_table_name}."content"::text, ''))) @@ (to_tsquery('simple', '!' || ''' ' || 'query' || ' ''')))}
|
|
67
|
+
)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
context "when options[:negation] is false" do
|
|
72
|
+
it "does not return a negated expression when a query is prepended with !" do
|
|
73
|
+
query = "!query"
|
|
74
|
+
columns = [
|
|
75
|
+
PgSearch::Configuration::Column.new(:name, nil, Model),
|
|
76
|
+
PgSearch::Configuration::Column.new(:content, nil, Model),
|
|
77
|
+
]
|
|
78
|
+
options = {:negation => false}
|
|
79
|
+
config = double(:config, :ignore => [])
|
|
80
|
+
normalizer = PgSearch::Normalizer.new(config)
|
|
81
|
+
|
|
82
|
+
feature = described_class.new(query, options, columns, Model, normalizer)
|
|
83
|
+
expect(feature.conditions.to_sql).to eq(
|
|
84
|
+
%Q{((to_tsvector('simple', coalesce(#{Model.quoted_table_name}."name"::text, '')) || to_tsvector('simple', coalesce(#{Model.quoted_table_name}."content"::text, ''))) @@ (to_tsquery('simple', ''' ' || '!query' || ' ''')))}
|
|
85
|
+
)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
context "when options[:tsvector_column] is a string" do
|
|
90
|
+
it 'uses the tsvector column' do
|
|
91
|
+
query = "query"
|
|
92
|
+
columns = [
|
|
93
|
+
PgSearch::Configuration::Column.new(:name, nil, Model),
|
|
94
|
+
PgSearch::Configuration::Column.new(:content, nil, Model),
|
|
95
|
+
]
|
|
96
|
+
options = { tsvector_column: "my_tsvector" }
|
|
97
|
+
config = double(:config, :ignore => [])
|
|
98
|
+
normalizer = PgSearch::Normalizer.new(config)
|
|
99
|
+
|
|
100
|
+
feature = described_class.new(query, options, columns, Model, normalizer)
|
|
101
|
+
expect(feature.conditions.to_sql).to eq(
|
|
102
|
+
%Q{((#{Model.quoted_table_name}.\"my_tsvector\") @@ (to_tsquery('simple', ''' ' || 'query' || ' ''')))}
|
|
103
|
+
)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
context "when options[:tsvector_column] is an array of strings" do
|
|
108
|
+
it 'uses the tsvector column' do
|
|
109
|
+
query = "query"
|
|
110
|
+
columns = [
|
|
111
|
+
PgSearch::Configuration::Column.new(:name, nil, Model),
|
|
112
|
+
PgSearch::Configuration::Column.new(:content, nil, Model),
|
|
113
|
+
]
|
|
114
|
+
options = { tsvector_column: ["tsvector1", "tsvector2"] }
|
|
115
|
+
config = double(:config, :ignore => [])
|
|
116
|
+
normalizer = PgSearch::Normalizer.new(config)
|
|
117
|
+
|
|
118
|
+
feature = described_class.new(query, options, columns, Model, normalizer)
|
|
119
|
+
expect(feature.conditions.to_sql).to eq(
|
|
120
|
+
%Q{((#{Model.quoted_table_name}.\"tsvector1\" || #{Model.quoted_table_name}.\"tsvector2\") @@ (to_tsquery('simple', ''' ' || 'query' || ' ''')))}
|
|
121
|
+
)
|
|
122
|
+
end
|
|
123
|
+
end
|
|
52
124
|
end
|
|
53
125
|
end
|
|
@@ -121,7 +121,7 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
|
121
121
|
ActiveSupport::Notifications.unsubscribe(notifier)
|
|
122
122
|
|
|
123
123
|
expect(executed_sql.length).to eq(1)
|
|
124
|
-
expect(executed_sql.first).to eq(expected_sql)
|
|
124
|
+
expect(executed_sql.first.strip).to eq(expected_sql.strip)
|
|
125
125
|
end
|
|
126
126
|
|
|
127
127
|
context "for a model with a non-standard primary key" do
|
|
@@ -177,7 +177,7 @@ describe PgSearch::Multisearch::Rebuilder do
|
|
|
177
177
|
ActiveSupport::Notifications.unsubscribe(notifier)
|
|
178
178
|
|
|
179
179
|
expect(executed_sql.length).to eq(1)
|
|
180
|
-
expect(executed_sql.first).to eq(expected_sql)
|
|
180
|
+
expect(executed_sql.first.strip).to eq(expected_sql.strip)
|
|
181
181
|
end
|
|
182
182
|
end
|
|
183
183
|
end
|
|
@@ -129,11 +129,11 @@ describe PgSearch::Multisearch do
|
|
|
129
129
|
SQL
|
|
130
130
|
|
|
131
131
|
statements = []
|
|
132
|
-
allow(connection).to receive(:execute) { |sql| statements << sql }
|
|
132
|
+
allow(connection).to receive(:execute) { |sql| statements << sql.strip }
|
|
133
133
|
|
|
134
134
|
PgSearch::Multisearch.rebuild(model)
|
|
135
135
|
|
|
136
|
-
expect(statements).to include(expected_sql)
|
|
136
|
+
expect(statements).to include(expected_sql.strip)
|
|
137
137
|
end
|
|
138
138
|
end
|
|
139
139
|
|
|
@@ -156,11 +156,11 @@ describe PgSearch::Multisearch do
|
|
|
156
156
|
SQL
|
|
157
157
|
|
|
158
158
|
statements = []
|
|
159
|
-
allow(connection).to receive(:execute) { |sql| statements << sql }
|
|
159
|
+
allow(connection).to receive(:execute) { |sql| statements << sql.strip }
|
|
160
160
|
|
|
161
161
|
PgSearch::Multisearch.rebuild(model)
|
|
162
162
|
|
|
163
|
-
expect(statements).to include(expected_sql)
|
|
163
|
+
expect(statements).to include(expected_sql.strip)
|
|
164
164
|
end
|
|
165
165
|
end
|
|
166
166
|
end
|
data/spec/spec_helper.rb
CHANGED
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.7.
|
|
4
|
+
version: 0.7.9
|
|
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:
|
|
12
|
+
date: 2015-02-04 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: activerecord
|
|
@@ -97,6 +97,20 @@ dependencies:
|
|
|
97
97
|
version: '3.0'
|
|
98
98
|
- !ruby/object:Gem::Dependency
|
|
99
99
|
name: with_model
|
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
|
101
|
+
requirements:
|
|
102
|
+
- - ">="
|
|
103
|
+
- !ruby/object:Gem::Version
|
|
104
|
+
version: '1.2'
|
|
105
|
+
type: :development
|
|
106
|
+
prerelease: false
|
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
108
|
+
requirements:
|
|
109
|
+
- - ">="
|
|
110
|
+
- !ruby/object:Gem::Version
|
|
111
|
+
version: '1.2'
|
|
112
|
+
- !ruby/object:Gem::Dependency
|
|
113
|
+
name: rubocop
|
|
100
114
|
requirement: !ruby/object:Gem::Requirement
|
|
101
115
|
requirements:
|
|
102
116
|
- - ">="
|
|
@@ -121,6 +135,8 @@ files:
|
|
|
121
135
|
- ".autotest"
|
|
122
136
|
- ".gitignore"
|
|
123
137
|
- ".rspec"
|
|
138
|
+
- ".rubocop.yml"
|
|
139
|
+
- ".rubocop_todo.yml"
|
|
124
140
|
- ".travis.yml"
|
|
125
141
|
- CHANGELOG.md
|
|
126
142
|
- CONTRIBUTING.md
|
|
@@ -130,6 +146,7 @@ files:
|
|
|
130
146
|
- README.md
|
|
131
147
|
- Rakefile
|
|
132
148
|
- bin/guard
|
|
149
|
+
- bin/rake
|
|
133
150
|
- bin/rspec
|
|
134
151
|
- lib/pg_search.rb
|
|
135
152
|
- lib/pg_search/compatibility.rb
|
|
@@ -175,7 +192,6 @@ files:
|
|
|
175
192
|
- spec/lib/pg_search/multisearchable_spec.rb
|
|
176
193
|
- spec/lib/pg_search/normalizer_spec.rb
|
|
177
194
|
- spec/spec_helper.rb
|
|
178
|
-
- spec/support/coveralls.rb
|
|
179
195
|
- spec/support/database.rb
|
|
180
196
|
- spec/support/with_model.rb
|
|
181
197
|
- sql/array_agg.sql
|
|
@@ -204,7 +220,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
204
220
|
version: '0'
|
|
205
221
|
requirements: []
|
|
206
222
|
rubyforge_project:
|
|
207
|
-
rubygems_version: 2.
|
|
223
|
+
rubygems_version: 2.4.5
|
|
208
224
|
signing_key:
|
|
209
225
|
specification_version: 4
|
|
210
226
|
summary: PgSearch builds Active Record named scopes that take advantage of PostgreSQL's
|
|
@@ -225,6 +241,5 @@ test_files:
|
|
|
225
241
|
- spec/lib/pg_search/multisearchable_spec.rb
|
|
226
242
|
- spec/lib/pg_search/normalizer_spec.rb
|
|
227
243
|
- spec/spec_helper.rb
|
|
228
|
-
- spec/support/coveralls.rb
|
|
229
244
|
- spec/support/database.rb
|
|
230
245
|
- spec/support/with_model.rb
|