pg_search 0.2 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,7 @@
1
+ ### 0.2.1
2
+
3
+ * Backport support for searching against tsvector columns (Kris Hicks)
4
+
1
5
  ### 0.2
2
6
 
3
7
  * Set dictionary to :simple by default for :tsearch. Before it was unset,
data/README.rdoc CHANGED
@@ -302,6 +302,32 @@ Ignoring accents uses the {unaccent contrib package}[http://www.postgresql.org/d
302
302
  SpanishQuestion.gringo_search("Que") # => [what]
303
303
  SpanishQuestion.gringo_search("Cüåñtô") # => [how_many]
304
304
 
305
+ === Using tsvector columns
306
+
307
+ PostgreSQL allows you the ability to search against a column with type tsvector instead of using an expression; this speeds up searching dramatically as it offloads creation of the tsvector that the tsquery is evaluated against.
308
+
309
+ To use this functionality you'll need to do a few things:
310
+
311
+ * Create a column of type tsvector that you'd like to search against. If you want to search using multiple search methods, for example tsearch and dmetaphone, you'll need a column for each.
312
+ * Create a trigger function that will update the column(s) using the expression appropriate for that type of search. See: http://www.postgresql.org/docs/current/static/textsearch-features.html#TEXTSEARCH-UPDATE-TRIGGERS
313
+ * Should you have any pre-existing data in the table, update the newly-created tsvector columns with the expression that your trigger function uses.
314
+ * Add the option to pg_search_scope, e.g:
315
+
316
+ pg_search_scope :fast_content_search,
317
+ :against => :content,
318
+ :using => {
319
+ dmetaphone: {
320
+ tsvector_column: 'tsvector_content_dmetaphone'
321
+ },
322
+ tsearch: {
323
+ dictionary: 'english',
324
+ tsvector_column: 'tsvector_content_tsearch'
325
+ }
326
+ trigram: {} # trigram does not use tsvectors
327
+ }
328
+
329
+ Please note that the :against column is only used when the tsvector_column is not present for the search type.
330
+
305
331
  == REQUIREMENTS
306
332
 
307
333
  * ActiveRecord 2 or 3
@@ -50,10 +50,14 @@ module PgSearch
50
50
  end
51
51
 
52
52
  def tsdocument
53
- @columns.map do |search_column|
54
- tsvector = "to_tsvector(:dictionary, #{@normalizer.add_normalization(search_column.to_sql)})"
55
- search_column.weight.nil? ? tsvector : "setweight(#{tsvector}, #{connection.quote(search_column.weight)})"
56
- end.join(" || ")
53
+ if @options[:tsvector_column]
54
+ @options[:tsvector_column].to_s
55
+ else
56
+ @columns.map do |search_column|
57
+ tsvector = "to_tsvector(:dictionary, #{@normalizer.add_normalization(search_column.to_sql)})"
58
+ search_column.weight.nil? ? tsvector : "setweight(#{tsvector}, #{connection.quote(search_column.weight)})"
59
+ end.join(" || ")
60
+ end
57
61
  end
58
62
 
59
63
  def tsearch_rank
@@ -1,3 +1,3 @@
1
1
  module PgSearch
2
- VERSION = "0.2"
2
+ VERSION = "0.2.1"
3
3
  end
@@ -5,13 +5,13 @@ describe PgSearch do
5
5
  if defined?(ActiveRecord::Relation)
6
6
  context "with Arel support" do
7
7
  context "without an :against" do
8
- with_model :associated_model do
8
+ with_model :AssociatedModel do
9
9
  table do |t|
10
10
  t.string "title"
11
11
  end
12
12
  end
13
13
 
14
- with_model :model_without_against do
14
+ with_model :ModelWithoutAgainst do
15
15
  table do |t|
16
16
  t.string "title"
17
17
  t.belongs_to :another_model
@@ -26,29 +26,29 @@ describe PgSearch do
26
26
  end
27
27
 
28
28
  it "returns rows that match the query in the columns of the associated model only" do
29
- associated = associated_model.create!(:title => 'abcdef')
29
+ associated = AssociatedModel.create!(:title => 'abcdef')
30
30
  included = [
31
- model_without_against.create!(:title => 'abcdef', :another_model => associated),
32
- model_without_against.create!(:title => 'ghijkl', :another_model => associated)
31
+ ModelWithoutAgainst.create!(:title => 'abcdef', :another_model => associated),
32
+ ModelWithoutAgainst.create!(:title => 'ghijkl', :another_model => associated)
33
33
  ]
34
34
  excluded = [
35
- model_without_against.create!(:title => 'abcdef')
35
+ ModelWithoutAgainst.create!(:title => 'abcdef')
36
36
  ]
37
37
 
38
- results = model_without_against.with_another('abcdef')
38
+ results = ModelWithoutAgainst.with_another('abcdef')
39
39
  results.map(&:title).should =~ included.map(&:title)
40
40
  results.should_not include(excluded)
41
41
  end
42
42
  end
43
43
 
44
44
  context "through a belongs_to association" do
45
- with_model :associated_model do
45
+ with_model :AssociatedModel do
46
46
  table do |t|
47
47
  t.string 'title'
48
48
  end
49
49
  end
50
50
 
51
- with_model :model_with_belongs_to do
51
+ with_model :ModelWithBelongsTo do
52
52
  table do |t|
53
53
  t.string 'title'
54
54
  t.belongs_to 'another_model'
@@ -63,36 +63,36 @@ describe PgSearch do
63
63
  end
64
64
 
65
65
  it "returns rows that match the query in either its own columns or the columns of the associated model" do
66
- associated = associated_model.create!(:title => 'abcdef')
66
+ associated = AssociatedModel.create!(:title => 'abcdef')
67
67
  included = [
68
- model_with_belongs_to.create!(:title => 'ghijkl', :another_model => associated),
69
- model_with_belongs_to.create!(:title => 'abcdef')
68
+ ModelWithBelongsTo.create!(:title => 'ghijkl', :another_model => associated),
69
+ ModelWithBelongsTo.create!(:title => 'abcdef')
70
70
  ]
71
- excluded = model_with_belongs_to.create!(:title => 'mnopqr',
72
- :another_model => associated_model.create!(:title => 'stuvwx'))
71
+ excluded = ModelWithBelongsTo.create!(:title => 'mnopqr',
72
+ :another_model => AssociatedModel.create!(:title => 'stuvwx'))
73
73
 
74
- results = model_with_belongs_to.with_associated('abcdef')
74
+ results = ModelWithBelongsTo.with_associated('abcdef')
75
75
  results.map(&:title).should =~ included.map(&:title)
76
76
  results.should_not include(excluded)
77
77
  end
78
78
  end
79
79
 
80
80
  context "through a has_many association" do
81
- with_model :associated_model_with_has_many do
81
+ with_model :AssociatedModelWithHasMany do
82
82
  table do |t|
83
83
  t.string 'title'
84
- t.belongs_to 'model_with_has_many'
84
+ t.belongs_to 'ModelWithHasMany'
85
85
  end
86
86
  end
87
87
 
88
- with_model :model_with_has_many do
88
+ with_model :ModelWithHasMany do
89
89
  table do |t|
90
90
  t.string 'title'
91
91
  end
92
92
 
93
93
  model do
94
94
  include PgSearch
95
- has_many :other_models, :class_name => 'AssociatedModelWithHasMany', :foreign_key => 'model_with_has_many_id'
95
+ has_many :other_models, :class_name => 'AssociatedModelWithHasMany', :foreign_key => 'ModelWithHasMany_id'
96
96
 
97
97
  pg_search_scope :with_associated, :against => [:title], :associated_against => {:other_models => :title}
98
98
  end
@@ -100,21 +100,21 @@ describe PgSearch do
100
100
 
101
101
  it "returns rows that match the query in either its own columns or the columns of the associated model" do
102
102
  included = [
103
- model_with_has_many.create!(:title => 'abcdef', :other_models => [
104
- associated_model_with_has_many.create!(:title => 'foo'),
105
- associated_model_with_has_many.create!(:title => 'bar')
103
+ ModelWithHasMany.create!(:title => 'abcdef', :other_models => [
104
+ AssociatedModelWithHasMany.create!(:title => 'foo'),
105
+ AssociatedModelWithHasMany.create!(:title => 'bar')
106
106
  ]),
107
- model_with_has_many.create!(:title => 'ghijkl', :other_models => [
108
- associated_model_with_has_many.create!(:title => 'foo bar'),
109
- associated_model_with_has_many.create!(:title => 'mnopqr')
107
+ ModelWithHasMany.create!(:title => 'ghijkl', :other_models => [
108
+ AssociatedModelWithHasMany.create!(:title => 'foo bar'),
109
+ AssociatedModelWithHasMany.create!(:title => 'mnopqr')
110
110
  ]),
111
- model_with_has_many.create!(:title => 'foo bar')
111
+ ModelWithHasMany.create!(:title => 'foo bar')
112
112
  ]
113
- excluded = model_with_has_many.create!(:title => 'stuvwx', :other_models => [
114
- associated_model_with_has_many.create!(:title => 'abcdef')
113
+ excluded = ModelWithHasMany.create!(:title => 'stuvwx', :other_models => [
114
+ AssociatedModelWithHasMany.create!(:title => 'abcdef')
115
115
  ])
116
116
 
117
- results = model_with_has_many.with_associated('foo bar')
117
+ results = ModelWithHasMany.with_associated('foo bar')
118
118
  results.map(&:title).should =~ included.map(&:title)
119
119
  results.should_not include(excluded)
120
120
  end
@@ -122,7 +122,7 @@ describe PgSearch do
122
122
 
123
123
  context "across multiple associations" do
124
124
  context "on different tables" do
125
- with_model :first_associated_model do
125
+ with_model :FirstAssociatedModel do
126
126
  table do |t|
127
127
  t.string 'title'
128
128
  t.belongs_to 'model_with_many_associations'
@@ -130,14 +130,14 @@ describe PgSearch do
130
130
  model {}
131
131
  end
132
132
 
133
- with_model :second_associated_model do
133
+ with_model :SecondAssociatedModel do
134
134
  table do |t|
135
135
  t.string 'title'
136
136
  end
137
137
  model {}
138
138
  end
139
139
 
140
- with_model :model_with_many_associations do
140
+ with_model :ModelWithManyAssociations do
141
141
  table do |t|
142
142
  t.string 'title'
143
143
  t.belongs_to 'model_of_second_type'
@@ -154,24 +154,24 @@ describe PgSearch do
154
154
  end
155
155
 
156
156
  it "returns rows that match the query in either its own columns or the columns of the associated model" do
157
- matching_second = second_associated_model.create!(:title => "foo bar")
158
- unmatching_second = second_associated_model.create!(:title => "uiop")
157
+ matching_second = SecondAssociatedModel.create!(:title => "foo bar")
158
+ unmatching_second = SecondAssociatedModel.create!(:title => "uiop")
159
159
 
160
160
  included = [
161
161
  ModelWithManyAssociations.create!(:title => 'abcdef', :models_of_first_type => [
162
- first_associated_model.create!(:title => 'foo'),
163
- first_associated_model.create!(:title => 'bar')
162
+ FirstAssociatedModel.create!(:title => 'foo'),
163
+ FirstAssociatedModel.create!(:title => 'bar')
164
164
  ]),
165
165
  ModelWithManyAssociations.create!(:title => 'ghijkl', :models_of_first_type => [
166
- first_associated_model.create!(:title => 'foo bar'),
167
- first_associated_model.create!(:title => 'mnopqr')
166
+ FirstAssociatedModel.create!(:title => 'foo bar'),
167
+ FirstAssociatedModel.create!(:title => 'mnopqr')
168
168
  ]),
169
169
  ModelWithManyAssociations.create!(:title => 'foo bar'),
170
170
  ModelWithManyAssociations.create!(:title => 'qwerty', :model_of_second_type => matching_second)
171
171
  ]
172
172
  excluded = [
173
173
  ModelWithManyAssociations.create!(:title => 'stuvwx', :models_of_first_type => [
174
- first_associated_model.create!(:title => 'abcdef')
174
+ FirstAssociatedModel.create!(:title => 'abcdef')
175
175
  ]),
176
176
  ModelWithManyAssociations.create!(:title => 'qwerty', :model_of_second_type => unmatching_second)
177
177
  ]
@@ -183,7 +183,7 @@ describe PgSearch do
183
183
  end
184
184
 
185
185
  context "on the same table" do
186
- with_model :doubly_associated_model do
186
+ with_model :DoublyAssociatedModel do
187
187
  table do |t|
188
188
  t.string 'title'
189
189
  t.belongs_to 'model_with_double_association'
@@ -237,16 +237,16 @@ describe PgSearch do
237
237
  end
238
238
  end
239
239
  end
240
-
240
+
241
241
  context "against multiple attributes on one association" do
242
- with_model :associated_model do
242
+ with_model :AssociatedModel do
243
243
  table do |t|
244
244
  t.string 'title'
245
245
  t.text 'author'
246
246
  end
247
247
  end
248
248
 
249
- with_model :model_with_association do
249
+ with_model :ModelWithAssociation do
250
250
  table do |t|
251
251
  t.belongs_to 'another_model'
252
252
  end
@@ -258,7 +258,7 @@ describe PgSearch do
258
258
  pg_search_scope :with_associated, :associated_against => {:another_model => [:title, :author]}
259
259
  end
260
260
  end
261
-
261
+
262
262
  it "should only do one join" do
263
263
  included = [
264
264
  ModelWithAssociation.create!(
@@ -289,12 +289,12 @@ describe PgSearch do
289
289
  included.each { |object| results.should include(object) }
290
290
  excluded.each { |object| results.should_not include(object) }
291
291
  end
292
-
292
+
293
293
  end
294
294
  end
295
295
  else
296
296
  context "without Arel support" do
297
- with_model :model do
297
+ with_model :Model do
298
298
  table do |t|
299
299
  t.string 'title'
300
300
  end
@@ -2,7 +2,7 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
3
  describe "an ActiveRecord model which includes PgSearch" do
4
4
 
5
- with_model :model_with_pg_search do
5
+ with_model :ModelWithPgSearch do
6
6
  table do |t|
7
7
  t.string 'title'
8
8
  t.text 'content'
@@ -16,18 +16,18 @@ describe "an ActiveRecord model which includes PgSearch" do
16
16
 
17
17
  describe ".pg_search_scope" do
18
18
  it "builds a scope" do
19
- model_with_pg_search.class_eval do
19
+ ModelWithPgSearch.class_eval do
20
20
  pg_search_scope "matching_query", :against => []
21
21
  end
22
22
 
23
23
  lambda {
24
- model_with_pg_search.scoped({}).matching_query("foo").scoped({})
24
+ ModelWithPgSearch.scoped({}).matching_query("foo").scoped({})
25
25
  }.should_not raise_error
26
26
  end
27
27
 
28
28
  context "when passed a lambda" do
29
29
  it "builds a dynamic scope" do
30
- model_with_pg_search.class_eval do
30
+ ModelWithPgSearch.class_eval do
31
31
  pg_search_scope :search_title_or_content, lambda { |query, pick_content|
32
32
  {
33
33
  :query => query.gsub("-remove-", ""),
@@ -36,31 +36,31 @@ describe "an ActiveRecord model which includes PgSearch" do
36
36
  }
37
37
  end
38
38
 
39
- included = model_with_pg_search.create!(:title => 'foo', :content => 'bar')
40
- excluded = model_with_pg_search.create!(:title => 'bar', :content => 'foo')
39
+ included = ModelWithPgSearch.create!(:title => 'foo', :content => 'bar')
40
+ excluded = ModelWithPgSearch.create!(:title => 'bar', :content => 'foo')
41
41
 
42
- model_with_pg_search.search_title_or_content('fo-remove-o', false).should == [included]
43
- model_with_pg_search.search_title_or_content('b-remove-ar', true).should == [included]
42
+ ModelWithPgSearch.search_title_or_content('fo-remove-o', false).should == [included]
43
+ ModelWithPgSearch.search_title_or_content('b-remove-ar', true).should == [included]
44
44
  end
45
45
  end
46
46
 
47
47
  context "when an unknown option is passed in" do
48
48
  it "raises an exception when invoked" do
49
49
  lambda {
50
- model_with_pg_search.class_eval do
50
+ ModelWithPgSearch.class_eval do
51
51
  pg_search_scope :with_unknown_option, :against => :content, :foo => :bar
52
52
  end
53
- model_with_pg_search.with_unknown_option("foo")
53
+ ModelWithPgSearch.with_unknown_option("foo")
54
54
  }.should raise_error(ArgumentError, /foo/)
55
55
  end
56
56
 
57
57
  context "dynamically" do
58
58
  it "raises an exception when invoked" do
59
59
  lambda {
60
- model_with_pg_search.class_eval do
60
+ ModelWithPgSearch.class_eval do
61
61
  pg_search_scope :with_unknown_option, lambda { |*| {:against => :content, :foo => :bar} }
62
62
  end
63
- model_with_pg_search.with_unknown_option("foo")
63
+ ModelWithPgSearch.with_unknown_option("foo")
64
64
  }.should raise_error(ArgumentError, /foo/)
65
65
  end
66
66
  end
@@ -69,20 +69,20 @@ describe "an ActiveRecord model which includes PgSearch" do
69
69
  context "when an unknown :using is passed" do
70
70
  it "raises an exception when invoked" do
71
71
  lambda {
72
- model_with_pg_search.class_eval do
72
+ ModelWithPgSearch.class_eval do
73
73
  pg_search_scope :with_unknown_using, :against => :content, :using => :foo
74
74
  end
75
- model_with_pg_search.with_unknown_using("foo")
75
+ ModelWithPgSearch.with_unknown_using("foo")
76
76
  }.should raise_error(ArgumentError, /foo/)
77
77
  end
78
78
 
79
79
  context "dynamically" do
80
80
  it "raises an exception when invoked" do
81
81
  lambda {
82
- model_with_pg_search.class_eval do
82
+ ModelWithPgSearch.class_eval do
83
83
  pg_search_scope :with_unknown_using, lambda { |*| {:against => :content, :using => :foo} }
84
84
  end
85
- model_with_pg_search.with_unknown_using("foo")
85
+ ModelWithPgSearch.with_unknown_using("foo")
86
86
  }.should raise_error(ArgumentError, /foo/)
87
87
  end
88
88
  end
@@ -91,20 +91,20 @@ describe "an ActiveRecord model which includes PgSearch" do
91
91
  context "when an unknown :ignoring is passed" do
92
92
  it "raises an exception when invoked" do
93
93
  lambda {
94
- model_with_pg_search.class_eval do
94
+ ModelWithPgSearch.class_eval do
95
95
  pg_search_scope :with_unknown_ignoring, :against => :content, :ignoring => :foo
96
96
  end
97
- model_with_pg_search.with_unknown_ignoring("foo")
97
+ ModelWithPgSearch.with_unknown_ignoring("foo")
98
98
  }.should raise_error(ArgumentError, /ignoring.*foo/)
99
99
  end
100
100
 
101
101
  context "dynamically" do
102
102
  it "raises an exception when invoked" do
103
103
  lambda {
104
- model_with_pg_search.class_eval do
104
+ ModelWithPgSearch.class_eval do
105
105
  pg_search_scope :with_unknown_ignoring, lambda { |*| {:against => :content, :ignoring => :foo} }
106
106
  end
107
- model_with_pg_search.with_unknown_ignoring("foo")
107
+ ModelWithPgSearch.with_unknown_ignoring("foo")
108
108
  }.should raise_error(ArgumentError, /ignoring.*foo/)
109
109
  end
110
110
  end
@@ -112,19 +112,19 @@ describe "an ActiveRecord model which includes PgSearch" do
112
112
  context "when :against is not passed in" do
113
113
  it "raises an exception when invoked" do
114
114
  lambda {
115
- model_with_pg_search.class_eval do
115
+ ModelWithPgSearch.class_eval do
116
116
  pg_search_scope :with_unknown_ignoring, {}
117
117
  end
118
- model_with_pg_search.with_unknown_ignoring("foo")
118
+ ModelWithPgSearch.with_unknown_ignoring("foo")
119
119
  }.should raise_error(ArgumentError, /against/)
120
120
  end
121
121
  context "dynamically" do
122
122
  it "raises an exception when invoked" do
123
123
  lambda {
124
- model_with_pg_search.class_eval do
124
+ ModelWithPgSearch.class_eval do
125
125
  pg_search_scope :with_unknown_ignoring, lambda { |*| {} }
126
126
  end
127
- model_with_pg_search.with_unknown_ignoring("foo")
127
+ ModelWithPgSearch.with_unknown_ignoring("foo")
128
128
  }.should raise_error(ArgumentError, /against/)
129
129
  end
130
130
  end
@@ -135,33 +135,33 @@ describe "an ActiveRecord model which includes PgSearch" do
135
135
  describe "a search scope" do
136
136
  context "against a single column" do
137
137
  before do
138
- model_with_pg_search.class_eval do
138
+ ModelWithPgSearch.class_eval do
139
139
  pg_search_scope :search_content, :against => :content
140
140
  end
141
141
  end
142
142
 
143
143
  it "returns an empty array when a blank query is passed in" do
144
- model_with_pg_search.create!(:content => 'foo')
144
+ ModelWithPgSearch.create!(:content => 'foo')
145
145
 
146
- results = model_with_pg_search.search_content('')
146
+ results = ModelWithPgSearch.search_content('')
147
147
  results.should == []
148
148
  end
149
149
 
150
150
  it "returns rows where the column contains the term in the query" do
151
- included = model_with_pg_search.create!(:content => 'foo')
152
- excluded = model_with_pg_search.create!(:content => 'bar')
151
+ included = ModelWithPgSearch.create!(:content => 'foo')
152
+ excluded = ModelWithPgSearch.create!(:content => 'bar')
153
153
 
154
- results = model_with_pg_search.search_content('foo')
154
+ results = ModelWithPgSearch.search_content('foo')
155
155
  results.should include(included)
156
156
  results.should_not include(excluded)
157
157
  end
158
158
 
159
159
  it "returns rows where the column contains all the terms in the query in any order" do
160
- included = [model_with_pg_search.create!(:content => 'foo bar'),
161
- model_with_pg_search.create!(:content => 'bar foo')]
162
- excluded = model_with_pg_search.create!(:content => 'foo')
160
+ included = [ModelWithPgSearch.create!(:content => 'foo bar'),
161
+ ModelWithPgSearch.create!(:content => 'bar foo')]
162
+ excluded = ModelWithPgSearch.create!(:content => 'foo')
163
163
 
164
- results = model_with_pg_search.search_content('foo bar')
164
+ results = ModelWithPgSearch.search_content('foo bar')
165
165
  results.should =~ included
166
166
  results.should_not include(excluded)
167
167
  end
@@ -170,10 +170,10 @@ describe "an ActiveRecord model which includes PgSearch" do
170
170
  # \303\241 is a with acute accent
171
171
  # \303\251 is e with acute accent
172
172
 
173
- included = [model_with_pg_search.create!(:content => "foo"),
174
- model_with_pg_search.create!(:content => "FOO")]
173
+ included = [ModelWithPgSearch.create!(:content => "foo"),
174
+ ModelWithPgSearch.create!(:content => "FOO")]
175
175
 
176
- results = model_with_pg_search.search_content("Foo")
176
+ results = ModelWithPgSearch.search_content("Foo")
177
177
  results.should =~ included
178
178
  end
179
179
 
@@ -181,97 +181,97 @@ describe "an ActiveRecord model which includes PgSearch" do
181
181
  # \303\241 is a with acute accent
182
182
  # \303\251 is e with acute accent
183
183
 
184
- included = model_with_pg_search.create!(:content => "abcd\303\251f")
185
- excluded = model_with_pg_search.create!(:content => "\303\241bcdef")
184
+ included = ModelWithPgSearch.create!(:content => "abcd\303\251f")
185
+ excluded = ModelWithPgSearch.create!(:content => "\303\241bcdef")
186
186
 
187
- results = model_with_pg_search.search_content("abcd\303\251f")
187
+ results = ModelWithPgSearch.search_content("abcd\303\251f")
188
188
  results.should == [included]
189
189
  results.should_not include(excluded)
190
190
  end
191
191
 
192
192
  it "returns rows that match the query but not rows that are prefixed by the query" do
193
- included = model_with_pg_search.create!(:content => 'pre')
194
- excluded = model_with_pg_search.create!(:content => 'prefix')
193
+ included = ModelWithPgSearch.create!(:content => 'pre')
194
+ excluded = ModelWithPgSearch.create!(:content => 'prefix')
195
195
 
196
- results = model_with_pg_search.search_content("pre")
196
+ results = ModelWithPgSearch.search_content("pre")
197
197
  results.should == [included]
198
198
  results.should_not include(excluded)
199
199
  end
200
200
 
201
201
  it "returns rows that match the query exactly and not those that match the query when stemmed by the default english dictionary" do
202
- included = model_with_pg_search.create!(:content => "jumped")
203
- excluded = [model_with_pg_search.create!(:content => "jump"),
204
- model_with_pg_search.create!(:content => "jumping")]
202
+ included = ModelWithPgSearch.create!(:content => "jumped")
203
+ excluded = [ModelWithPgSearch.create!(:content => "jump"),
204
+ ModelWithPgSearch.create!(:content => "jumping")]
205
205
 
206
- results = model_with_pg_search.search_content("jumped")
206
+ results = ModelWithPgSearch.search_content("jumped")
207
207
  results.should == [included]
208
208
  end
209
209
 
210
210
  it "returns rows that match sorted by rank" do
211
- loser = model_with_pg_search.create!(:content => 'foo')
212
- winner = model_with_pg_search.create!(:content => 'foo foo')
211
+ loser = ModelWithPgSearch.create!(:content => 'foo')
212
+ winner = ModelWithPgSearch.create!(:content => 'foo foo')
213
213
 
214
- results = model_with_pg_search.search_content("foo")
214
+ results = ModelWithPgSearch.search_content("foo")
215
215
  results[0].rank.should > results[1].rank
216
216
  results.should == [winner, loser]
217
217
  end
218
218
 
219
219
  it "returns results that match sorted by primary key for records that rank the same" do
220
- sorted_results = [model_with_pg_search.create!(:content => 'foo'),
221
- model_with_pg_search.create!(:content => 'foo')].sort_by(&:id)
220
+ sorted_results = [ModelWithPgSearch.create!(:content => 'foo'),
221
+ ModelWithPgSearch.create!(:content => 'foo')].sort_by(&:id)
222
222
 
223
- results = model_with_pg_search.search_content("foo")
223
+ results = ModelWithPgSearch.search_content("foo")
224
224
  results.should == sorted_results
225
225
  end
226
226
 
227
227
  it "returns results that match a query with multiple space-separated search terms" do
228
228
  included = [
229
- model_with_pg_search.create!(:content => 'foo bar'),
230
- model_with_pg_search.create!(:content => 'bar foo'),
231
- model_with_pg_search.create!(:content => 'bar foo baz'),
229
+ ModelWithPgSearch.create!(:content => 'foo bar'),
230
+ ModelWithPgSearch.create!(:content => 'bar foo'),
231
+ ModelWithPgSearch.create!(:content => 'bar foo baz'),
232
232
  ]
233
233
  excluded = [
234
- model_with_pg_search.create!(:content => 'foo'),
235
- model_with_pg_search.create!(:content => 'foo baz')
234
+ ModelWithPgSearch.create!(:content => 'foo'),
235
+ ModelWithPgSearch.create!(:content => 'foo baz')
236
236
  ]
237
237
 
238
- results = model_with_pg_search.search_content('foo bar')
238
+ results = ModelWithPgSearch.search_content('foo bar')
239
239
  results.should =~ included
240
240
  results.should_not include(excluded)
241
241
  end
242
242
 
243
243
  it "returns rows that match a query with characters that are invalid in a tsquery expression" do
244
- included = model_with_pg_search.create!(:content => "(:Foo.) Bar?, \\")
244
+ included = ModelWithPgSearch.create!(:content => "(:Foo.) Bar?, \\")
245
245
 
246
- results = model_with_pg_search.search_content("foo :bar .,?() \\")
246
+ results = ModelWithPgSearch.search_content("foo :bar .,?() \\")
247
247
  results.should == [included]
248
248
  end
249
249
 
250
250
  it "accepts non-string queries and calls #to_s on them" do
251
- foo = model_with_pg_search.create!(:content => "foo")
251
+ foo = ModelWithPgSearch.create!(:content => "foo")
252
252
  not_a_string = stub(:to_s => "foo")
253
- model_with_pg_search.search_content(not_a_string).should == [foo]
253
+ ModelWithPgSearch.search_content(not_a_string).should == [foo]
254
254
  end
255
255
  end
256
256
 
257
257
  context "against multiple columns" do
258
258
  before do
259
- model_with_pg_search.class_eval do
259
+ ModelWithPgSearch.class_eval do
260
260
  pg_search_scope :search_title_and_content, :against => [:title, :content]
261
261
  end
262
262
  end
263
263
 
264
264
  it "returns rows whose columns contain all of the terms in the query across columns" do
265
265
  included = [
266
- model_with_pg_search.create!(:title => 'foo', :content => 'bar'),
267
- model_with_pg_search.create!(:title => 'bar', :content => 'foo')
266
+ ModelWithPgSearch.create!(:title => 'foo', :content => 'bar'),
267
+ ModelWithPgSearch.create!(:title => 'bar', :content => 'foo')
268
268
  ]
269
269
  excluded = [
270
- model_with_pg_search.create!(:title => 'foo', :content => 'foo'),
271
- model_with_pg_search.create!(:title => 'bar', :content => 'bar')
270
+ ModelWithPgSearch.create!(:title => 'foo', :content => 'foo'),
271
+ ModelWithPgSearch.create!(:title => 'bar', :content => 'bar')
272
272
  ]
273
273
 
274
- results = model_with_pg_search.search_title_and_content('foo bar')
274
+ results = ModelWithPgSearch.search_title_and_content('foo bar')
275
275
 
276
276
  results.should =~ included
277
277
  excluded.each do |result|
@@ -280,37 +280,37 @@ describe "an ActiveRecord model which includes PgSearch" do
280
280
  end
281
281
 
282
282
  it "returns rows where at one column contains all of the terms in the query and another does not" do
283
- in_title = model_with_pg_search.create!(:title => 'foo', :content => 'bar')
284
- in_content = model_with_pg_search.create!(:title => 'bar', :content => 'foo')
283
+ in_title = ModelWithPgSearch.create!(:title => 'foo', :content => 'bar')
284
+ in_content = ModelWithPgSearch.create!(:title => 'bar', :content => 'foo')
285
285
 
286
- results = model_with_pg_search.search_title_and_content('foo')
286
+ results = ModelWithPgSearch.search_title_and_content('foo')
287
287
  results.should =~ [in_title, in_content]
288
288
  end
289
289
 
290
290
  # Searching with a NULL column will prevent any matches unless we coalesce it.
291
291
  it "returns rows where at one column contains all of the terms in the query and another is NULL" do
292
- included = model_with_pg_search.create!(:title => 'foo', :content => nil)
293
- results = model_with_pg_search.search_title_and_content('foo')
292
+ included = ModelWithPgSearch.create!(:title => 'foo', :content => nil)
293
+ results = ModelWithPgSearch.search_title_and_content('foo')
294
294
  results.should == [included]
295
295
  end
296
296
  end
297
297
 
298
298
  context "using trigram" do
299
299
  before do
300
- model_with_pg_search.class_eval do
300
+ ModelWithPgSearch.class_eval do
301
301
  pg_search_scope :with_trigrams, :against => [:title, :content], :using => :trigram
302
302
  end
303
303
  end
304
304
 
305
305
  it "returns rows where one searchable column and the query share enough trigrams" do
306
- included = model_with_pg_search.create!(:title => 'abcdefghijkl', :content => nil)
307
- results = model_with_pg_search.with_trigrams('cdefhijkl')
306
+ included = ModelWithPgSearch.create!(:title => 'abcdefghijkl', :content => nil)
307
+ results = ModelWithPgSearch.with_trigrams('cdefhijkl')
308
308
  results.should == [included]
309
309
  end
310
310
 
311
311
  it "returns rows where multiple searchable columns and the query share enough trigrams" do
312
- included = model_with_pg_search.create!(:title => 'abcdef', :content => 'ghijkl')
313
- results = model_with_pg_search.with_trigrams('cdefhijkl')
312
+ included = ModelWithPgSearch.create!(:title => 'abcdef', :content => 'ghijkl')
313
+ results = ModelWithPgSearch.with_trigrams('cdefhijkl')
314
314
  results.should == [included]
315
315
  end
316
316
  end
@@ -318,7 +318,7 @@ describe "an ActiveRecord model which includes PgSearch" do
318
318
  context "using tsearch" do
319
319
  context "with :prefix => true" do
320
320
  before do
321
- model_with_pg_search.class_eval do
321
+ ModelWithPgSearch.class_eval do
322
322
  pg_search_scope :search_title_with_prefixes,
323
323
  :against => :title,
324
324
  :using => {
@@ -328,22 +328,22 @@ describe "an ActiveRecord model which includes PgSearch" do
328
328
  end
329
329
 
330
330
  it "returns rows that match the query and that are prefixed by the query" do
331
- included = model_with_pg_search.create!(:title => 'prefix')
332
- excluded = model_with_pg_search.create!(:title => 'postfix')
331
+ included = ModelWithPgSearch.create!(:title => 'prefix')
332
+ excluded = ModelWithPgSearch.create!(:title => 'postfix')
333
333
 
334
- results = model_with_pg_search.search_title_with_prefixes("pre")
334
+ results = ModelWithPgSearch.search_title_with_prefixes("pre")
335
335
  results.should == [included]
336
336
  results.should_not include(excluded)
337
337
  end
338
338
 
339
339
  it "returns rows that match the query when the query has a hyphen" do
340
340
  included = [
341
- model_with_pg_search.create!(:title => 'foo bar'),
342
- model_with_pg_search.create!(:title => 'foo-bar')
341
+ ModelWithPgSearch.create!(:title => 'foo bar'),
342
+ ModelWithPgSearch.create!(:title => 'foo-bar')
343
343
  ]
344
- excluded = model_with_pg_search.create!(:title => 'baz quux')
344
+ excluded = ModelWithPgSearch.create!(:title => 'baz quux')
345
345
 
346
- results = model_with_pg_search.search_title_with_prefixes("foo-bar")
346
+ results = ModelWithPgSearch.search_title_with_prefixes("foo-bar")
347
347
  results.should =~ included
348
348
  results.should_not include(excluded)
349
349
  end
@@ -351,7 +351,7 @@ describe "an ActiveRecord model which includes PgSearch" do
351
351
 
352
352
  context "with the english dictionary" do
353
353
  before do
354
- model_with_pg_search.class_eval do
354
+ ModelWithPgSearch.class_eval do
355
355
  pg_search_scope :search_content_with_english,
356
356
  :against => :content,
357
357
  :using => {
@@ -361,27 +361,27 @@ describe "an ActiveRecord model which includes PgSearch" do
361
361
  end
362
362
 
363
363
  it "returns rows that match the query when stemmed by the english dictionary" do
364
- included = [model_with_pg_search.create!(:content => "jump"),
365
- model_with_pg_search.create!(:content => "jumped"),
366
- model_with_pg_search.create!(:content => "jumping")]
364
+ included = [ModelWithPgSearch.create!(:content => "jump"),
365
+ ModelWithPgSearch.create!(:content => "jumped"),
366
+ ModelWithPgSearch.create!(:content => "jumping")]
367
367
 
368
- results = model_with_pg_search.search_content_with_english("jump")
368
+ results = ModelWithPgSearch.search_content_with_english("jump")
369
369
  results.should =~ included
370
370
  end
371
371
  end
372
372
 
373
373
  context "against columns ranked with arrays" do
374
374
  before do
375
- model_with_pg_search.class_eval do
375
+ ModelWithPgSearch.class_eval do
376
376
  pg_search_scope :search_weighted_by_array_of_arrays, :against => [[:content, 'B'], [:title, 'A']]
377
377
  end
378
378
  end
379
379
 
380
380
  it "returns results sorted by weighted rank" do
381
- loser = model_with_pg_search.create!(:title => 'bar', :content => 'foo')
382
- winner = model_with_pg_search.create!(:title => 'foo', :content => 'bar')
381
+ loser = ModelWithPgSearch.create!(:title => 'bar', :content => 'foo')
382
+ winner = ModelWithPgSearch.create!(:title => 'foo', :content => 'bar')
383
383
 
384
- results = model_with_pg_search.search_weighted_by_array_of_arrays('foo')
384
+ results = ModelWithPgSearch.search_weighted_by_array_of_arrays('foo')
385
385
  results[0].rank.should > results[1].rank
386
386
  results.should == [winner, loser]
387
387
  end
@@ -389,16 +389,16 @@ describe "an ActiveRecord model which includes PgSearch" do
389
389
 
390
390
  context "against columns ranked with a hash" do
391
391
  before do
392
- model_with_pg_search.class_eval do
392
+ ModelWithPgSearch.class_eval do
393
393
  pg_search_scope :search_weighted_by_hash, :against => {:content => 'B', :title => 'A'}
394
394
  end
395
395
  end
396
396
 
397
397
  it "returns results sorted by weighted rank" do
398
- loser = model_with_pg_search.create!(:title => 'bar', :content => 'foo')
399
- winner = model_with_pg_search.create!(:title => 'foo', :content => 'bar')
398
+ loser = ModelWithPgSearch.create!(:title => 'bar', :content => 'foo')
399
+ winner = ModelWithPgSearch.create!(:title => 'foo', :content => 'bar')
400
400
 
401
- results = model_with_pg_search.search_weighted_by_hash('foo')
401
+ results = ModelWithPgSearch.search_weighted_by_hash('foo')
402
402
  results[0].rank.should > results[1].rank
403
403
  results.should == [winner, loser]
404
404
  end
@@ -406,16 +406,16 @@ describe "an ActiveRecord model which includes PgSearch" do
406
406
 
407
407
  context "against columns of which only some are ranked" do
408
408
  before do
409
- model_with_pg_search.class_eval do
409
+ ModelWithPgSearch.class_eval do
410
410
  pg_search_scope :search_weighted, :against => [:content, [:title, 'A']]
411
411
  end
412
412
  end
413
413
 
414
414
  it "returns results sorted by weighted rank using an implied low rank for unranked columns" do
415
- loser = model_with_pg_search.create!(:title => 'bar', :content => 'foo')
416
- winner = model_with_pg_search.create!(:title => 'foo', :content => 'bar')
415
+ loser = ModelWithPgSearch.create!(:title => 'bar', :content => 'foo')
416
+ winner = ModelWithPgSearch.create!(:title => 'foo', :content => 'bar')
417
417
 
418
- results = model_with_pg_search.search_weighted('foo')
418
+ results = ModelWithPgSearch.search_weighted('foo')
419
419
  results[0].rank.should > results[1].rank
420
420
  results.should == [winner, loser]
421
421
  end
@@ -424,46 +424,46 @@ describe "an ActiveRecord model which includes PgSearch" do
424
424
 
425
425
  context "using dmetaphone" do
426
426
  before do
427
- model_with_pg_search.class_eval do
427
+ ModelWithPgSearch.class_eval do
428
428
  pg_search_scope :with_dmetaphones, :against => [:title, :content], :using => :dmetaphone
429
429
  end
430
430
  end
431
431
 
432
432
  it "returns rows where one searchable column and the query share enough dmetaphones" do
433
- included = model_with_pg_search.create!(:title => 'Geoff', :content => nil)
434
- excluded = model_with_pg_search.create!(:title => 'Bob', :content => nil)
435
- results = model_with_pg_search.with_dmetaphones('Jeff')
433
+ included = ModelWithPgSearch.create!(:title => 'Geoff', :content => nil)
434
+ excluded = ModelWithPgSearch.create!(:title => 'Bob', :content => nil)
435
+ results = ModelWithPgSearch.with_dmetaphones('Jeff')
436
436
  results.should == [included]
437
437
  end
438
438
 
439
439
  it "returns rows where multiple searchable columns and the query share enough dmetaphones" do
440
- included = model_with_pg_search.create!(:title => 'Geoff', :content => 'George')
441
- excluded = model_with_pg_search.create!(:title => 'Bob', :content => 'Jones')
442
- results = model_with_pg_search.with_dmetaphones('Jeff Jorge')
440
+ included = ModelWithPgSearch.create!(:title => 'Geoff', :content => 'George')
441
+ excluded = ModelWithPgSearch.create!(:title => 'Bob', :content => 'Jones')
442
+ results = ModelWithPgSearch.with_dmetaphones('Jeff Jorge')
443
443
  results.should == [included]
444
444
  end
445
445
 
446
446
  it "returns rows that match dmetaphones that are English stopwords" do
447
- included = model_with_pg_search.create!(:title => 'White', :content => nil)
448
- excluded = model_with_pg_search.create!(:title => 'Black', :content => nil)
449
- results = model_with_pg_search.with_dmetaphones('Wight')
447
+ included = ModelWithPgSearch.create!(:title => 'White', :content => nil)
448
+ excluded = ModelWithPgSearch.create!(:title => 'Black', :content => nil)
449
+ results = ModelWithPgSearch.with_dmetaphones('Wight')
450
450
  results.should == [included]
451
451
  end
452
452
 
453
453
  it "can handle terms that do not have a dmetaphone equivalent" do
454
454
  term_with_blank_metaphone = "w"
455
455
 
456
- included = model_with_pg_search.create!(:title => 'White', :content => nil)
457
- excluded = model_with_pg_search.create!(:title => 'Black', :content => nil)
456
+ included = ModelWithPgSearch.create!(:title => 'White', :content => nil)
457
+ excluded = ModelWithPgSearch.create!(:title => 'Black', :content => nil)
458
458
 
459
- results = model_with_pg_search.with_dmetaphones('Wight W')
459
+ results = ModelWithPgSearch.with_dmetaphones('Wight W')
460
460
  results.should == [included]
461
461
  end
462
462
  end
463
463
 
464
464
  context "using multiple features" do
465
465
  before do
466
- model_with_pg_search.class_eval do
466
+ ModelWithPgSearch.class_eval do
467
467
  pg_search_scope :with_tsearch,
468
468
  :against => :title,
469
469
  :using => [
@@ -483,19 +483,19 @@ describe "an ActiveRecord model which includes PgSearch" do
483
483
  end
484
484
 
485
485
  it "returns rows that match using any of the features" do
486
- record = model_with_pg_search.create!(:title => "tiling is grouty")
486
+ record = ModelWithPgSearch.create!(:title => "tiling is grouty")
487
487
 
488
488
  # matches trigram only
489
489
  trigram_query = "ling is grouty"
490
- model_with_pg_search.with_trigram(trigram_query).should include(record)
491
- model_with_pg_search.with_tsearch(trigram_query).should_not include(record)
492
- model_with_pg_search.with_tsearch_and_trigram_using_array(trigram_query).should == [record]
490
+ ModelWithPgSearch.with_trigram(trigram_query).should include(record)
491
+ ModelWithPgSearch.with_tsearch(trigram_query).should_not include(record)
492
+ ModelWithPgSearch.with_tsearch_and_trigram_using_array(trigram_query).should == [record]
493
493
 
494
494
  # matches tsearch only
495
495
  tsearch_query = "til"
496
- model_with_pg_search.with_tsearch(tsearch_query).should include(record)
497
- model_with_pg_search.with_trigram(tsearch_query).should_not include(record)
498
- model_with_pg_search.with_tsearch_and_trigram_using_array(tsearch_query).should == [record]
496
+ ModelWithPgSearch.with_tsearch(tsearch_query).should include(record)
497
+ ModelWithPgSearch.with_trigram(tsearch_query).should_not include(record)
498
+ ModelWithPgSearch.with_tsearch_and_trigram_using_array(tsearch_query).should == [record]
499
499
  end
500
500
 
501
501
  context "with feature-specific configuration" do
@@ -503,7 +503,7 @@ describe "an ActiveRecord model which includes PgSearch" do
503
503
  @tsearch_config = tsearch_config = {:dictionary => 'english'}
504
504
  @trigram_config = trigram_config = {:foo => 'bar'}
505
505
 
506
- model_with_pg_search.class_eval do
506
+ ModelWithPgSearch.class_eval do
507
507
  pg_search_scope :with_tsearch_and_trigram_using_hash,
508
508
  :against => :title,
509
509
  :using => {
@@ -518,14 +518,56 @@ describe "an ActiveRecord model which includes PgSearch" do
518
518
  PgSearch::Features::TSearch.should_receive(:new).with(anything, @tsearch_config, anything, anything, anything).at_least(:once).and_return(stub_feature)
519
519
  PgSearch::Features::Trigram.should_receive(:new).with(anything, @trigram_config, anything, anything, anything).at_least(:once).and_return(stub_feature)
520
520
 
521
- model_with_pg_search.with_tsearch_and_trigram_using_hash("foo")
521
+ ModelWithPgSearch.with_tsearch_and_trigram_using_hash("foo")
522
522
  end
523
523
  end
524
524
  end
525
525
 
526
+ context "using a tsvector column" do
527
+ with_model :ModelWithPgSearchUsingTsVectorColumn do
528
+ table do |t|
529
+ t.text 'content'
530
+ t.column 'content_tsvector', :tsvector
531
+ end
532
+
533
+ model { include PgSearch }
534
+ end
535
+
536
+ let!(:expected) { ModelWithPgSearchUsingTsVectorColumn.create!(:content => 'tiling is grouty') }
537
+ let!(:unexpected) { ModelWithPgSearchUsingTsVectorColumn.create!(:content => 'longcat is looooooooong') }
538
+
539
+ before do
540
+ ActiveRecord::Base.connection.execute <<-SQL
541
+ UPDATE #{ModelWithPgSearchUsingTsVectorColumn.table_name}
542
+ SET content_tsvector = to_tsvector('english'::regconfig, "#{ModelWithPgSearchUsingTsVectorColumn.table_name}"."content")
543
+ SQL
544
+
545
+ ModelWithPgSearchUsingTsVectorColumn.class_eval do
546
+ pg_search_scope :search_by_content_with_tsvector,
547
+ :against => :content,
548
+ :using => {
549
+ :tsearch => {
550
+ :tsvector_column => 'content_tsvector',
551
+ :dictionary => 'english'
552
+ }
553
+ }
554
+ end
555
+ end
556
+
557
+ if defined?(ActiveRecord::Relation)
558
+ it "should not use to_tsvector in the query" do
559
+ ModelWithPgSearchUsingTsVectorColumn.search_by_content_with_tsvector("tiles").to_sql.should_not =~ /to_tsvector/
560
+ end
561
+ end
562
+
563
+ it "should find the expected result" do
564
+ ModelWithPgSearchUsingTsVectorColumn.search_by_content_with_tsvector("tiles").map(&:id).should == [expected.id]
565
+ end
566
+ end
567
+
526
568
  context "ignoring accents" do
527
569
  before do
528
- model_with_pg_search.class_eval do
570
+ ModelWithPgSearch.class_eval do
529
571
  pg_search_scope :search_title_without_accents, :against => :title, :ignoring => :accents
530
572
  end
531
573
  end
@@ -534,16 +576,16 @@ describe "an ActiveRecord model which includes PgSearch" do
534
576
  # \303\241 is a with acute accent
535
577
  # \303\251 is e with acute accent
536
578
 
537
- included = model_with_pg_search.create!(:title => "\303\241bcdef")
579
+ included = ModelWithPgSearch.create!(:title => "\303\241bcdef")
538
580
 
539
- results = model_with_pg_search.search_title_without_accents("abcd\303\251f")
581
+ results = ModelWithPgSearch.search_title_without_accents("abcd\303\251f")
540
582
  results.should == [included]
541
583
  end
542
584
  end
543
585
 
544
586
  context "when passed a :ranked_by expression" do
545
587
  before do
546
- model_with_pg_search.class_eval do
588
+ ModelWithPgSearch.class_eval do
547
589
  pg_search_scope :search_content_with_default_rank,
548
590
  :against => :content
549
591
  pg_search_scope :search_content_with_importance_as_rank,
@@ -556,28 +598,28 @@ describe "an ActiveRecord model which includes PgSearch" do
556
598
  end
557
599
 
558
600
  it "should return records with a rank attribute equal to the :ranked_by expression" do
559
- model_with_pg_search.create!(:content => 'foo', :importance => 10)
560
- results = model_with_pg_search.search_content_with_importance_as_rank("foo")
601
+ ModelWithPgSearch.create!(:content => 'foo', :importance => 10)
602
+ results = ModelWithPgSearch.search_content_with_importance_as_rank("foo")
561
603
  results.first.rank.should == 10
562
604
  end
563
605
 
564
606
  it "should substitute :tsearch with the tsearch rank expression in the :ranked_by expression" do
565
- model_with_pg_search.create!(:content => 'foo', :importance => 10)
607
+ ModelWithPgSearch.create!(:content => 'foo', :importance => 10)
566
608
 
567
- tsearch_rank = model_with_pg_search.search_content_with_default_rank("foo").first.rank
568
- multiplied_rank = model_with_pg_search.search_content_with_importance_as_rank_multiplier("foo").first.rank
609
+ tsearch_rank = ModelWithPgSearch.search_content_with_default_rank("foo").first.rank
610
+ multiplied_rank = ModelWithPgSearch.search_content_with_importance_as_rank_multiplier("foo").first.rank
569
611
 
570
612
  multiplied_rank.should be_within(0.001).of(tsearch_rank * 10)
571
613
  end
572
614
 
573
615
  it "should return results in descending order of the value of the rank expression" do
574
616
  records = [
575
- model_with_pg_search.create!(:content => 'foo', :importance => 1),
576
- model_with_pg_search.create!(:content => 'foo', :importance => 3),
577
- model_with_pg_search.create!(:content => 'foo', :importance => 2)
617
+ ModelWithPgSearch.create!(:content => 'foo', :importance => 1),
618
+ ModelWithPgSearch.create!(:content => 'foo', :importance => 3),
619
+ ModelWithPgSearch.create!(:content => 'foo', :importance => 2)
578
620
  ]
579
621
 
580
- results = model_with_pg_search.search_content_with_importance_as_rank("foo")
622
+ results = ModelWithPgSearch.search_content_with_importance_as_rank("foo")
581
623
  results.should == records.sort_by(&:importance).reverse
582
624
  end
583
625
 
@@ -586,7 +628,7 @@ describe "an ActiveRecord model which includes PgSearch" do
586
628
  context "using the #{feature} ranking algorithm" do
587
629
  before do
588
630
  @scope_name = scope_name = :"search_content_ranked_by_#{feature}"
589
- model_with_pg_search.class_eval do
631
+ ModelWithPgSearch.class_eval do
590
632
  pg_search_scope scope_name,
591
633
  :against => :content,
592
634
  :ranked_by => ":#{feature}"
@@ -594,9 +636,9 @@ describe "an ActiveRecord model which includes PgSearch" do
594
636
  end
595
637
 
596
638
  it "should return results with a rank" do
597
- model_with_pg_search.create!(:content => 'foo')
639
+ ModelWithPgSearch.create!(:content => 'foo')
598
640
 
599
- results = model_with_pg_search.send(@scope_name, 'foo')
641
+ results = ModelWithPgSearch.send(@scope_name, 'foo')
600
642
  results.first.rank.should_not be_nil
601
643
  end
602
644
  end
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg_search
3
3
  version: !ruby/object:Gem::Version
4
- hash: 15
4
+ hash: 21
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- version: "0.2"
9
+ - 1
10
+ version: 0.2.1
10
11
  platform: ruby
11
12
  authors:
12
13
  - Case Commons, LLC
@@ -14,7 +15,7 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2011-05-11 00:00:00 Z
18
+ date: 2011-12-15 00:00:00 Z
18
19
  dependencies: []
19
20
 
20
21
  description: PgSearch builds ActiveRecord named scopes that take advantage of PostgreSQL's full text search
@@ -89,7 +90,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
89
90
  requirements: []
90
91
 
91
92
  rubyforge_project:
92
- rubygems_version: 1.8.1
93
+ rubygems_version: 1.8.10
93
94
  signing_key:
94
95
  specification_version: 3
95
96
  summary: PgSearch builds ActiveRecord named scopes that take advantage of PostgreSQL's full text search