scoped_search 2.3.0 → 2.3.1

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.
data/lib/scoped_search.rb CHANGED
@@ -14,7 +14,7 @@ module ScopedSearch
14
14
 
15
15
  # The current scoped_search version. Do not change thisvalue by hand,
16
16
  # because it will be updated automatically by the gem release script.
17
- VERSION = "2.3.0"
17
+ VERSION = "2.3.1"
18
18
 
19
19
  # The ClassMethods module will be included into the ActiveRecord::Base class
20
20
  # to add the <tt>ActiveRecord::Base.scoped_search</tt> method and the
@@ -144,7 +144,7 @@ module ScopedSearch
144
144
  }
145
145
  end
146
146
 
147
- suggestions.uniq.map {|m| "#{q} #{m}".gsub(/\s+/," ")}
147
+ suggestions.uniq.map {|m| "#{q} #{m}"}
148
148
  end
149
149
 
150
150
  # suggest all searchable field names.
@@ -230,7 +230,7 @@ module ScopedSearch
230
230
  else
231
231
  opts.merge!(key_opts)
232
232
  end
233
- return field.klass.all(opts.merge(:limit => 20)).map(&field.field)
233
+ return field.klass.all(opts.merge(:limit => 20)).map(&field.field).compact.map{|v| v.to_s =~ /\s+/ ? "\"#{v}\"" : v}
234
234
  end
235
235
 
236
236
  #this method returns conditions for selecting completion from partial value
@@ -104,9 +104,15 @@ module ScopedSearch
104
104
  # By default, it will simply look up the correct SQL operator in the SQL_OPERATORS
105
105
  # hash, but this can be overridden by a database adapter.
106
106
  def sql_operator(operator, field)
107
+ raise ScopedSearch::QueryNotSupported, "the operator '#{operator}' is not supported for field type '#{field.type}'" if [:like, :unlike].include?(operator) and !field.textual?
107
108
  SQL_OPERATORS[operator]
108
109
  end
109
110
 
111
+ # Returns a NOT (...) SQL fragment that negates the current AST node's children
112
+ def to_not_sql(rhs, definition, &block)
113
+ "NOT COALESCE(#{rhs.to_sql(self, definition, &block)}, 0)"
114
+ end
115
+
110
116
  # Perform a comparison between a field and a Date(Time) value.
111
117
  #
112
118
  # This function makes sure the date is valid and adjust the comparison in
@@ -129,7 +135,8 @@ module ScopedSearch
129
135
  # but the field is of datetime type. Change the comparison to return
130
136
  # more logical results.
131
137
  if field.datetime?
132
- span = (timestamp.day_fraction == 0) ? 1.day : 1.hour
138
+ span = 1.minute if(value =~ /\A\s*\d+\s+\bminutes?\b\s+\bago\b\s*\z/i)
139
+ span ||= (timestamp.day_fraction == 0) ? 1.day : 1.hour
133
140
  if [:eq, :ne].include?(operator)
134
141
  # Instead of looking for an exact (non-)match, look for dates that
135
142
  # fall inside/outside the range of timestamps of that day.
@@ -187,12 +194,11 @@ module ScopedSearch
187
194
  # <tt>operator</tt>:: The operator used for comparison.
188
195
  # <tt>value</tt>:: The value to compare the field with.
189
196
  def sql_test(field, operator, value, lhs, &block) # :yields: finder_option_type, value
190
- if field.key_field
191
- yield(:parameter, lhs.sub(/^.*\./,''))
192
- end
193
- if field.ext_method
194
- return field.to_ext_method_sql(lhs, sql_operator(operator, field), value, &block)
195
- elsif [:like, :unlike].include?(operator)
197
+ return field.to_ext_method_sql(lhs, sql_operator(operator, field), value, &block) if field.ext_method
198
+
199
+ yield(:parameter, lhs.sub(/^.*\./,'')) if field.key_field
200
+
201
+ if [:like, :unlike].include?(operator)
196
202
  yield(:parameter, (value !~ /^\%|\*/ && value !~ /\%|\*$/) ? "%#{value}%" : value.tr_s('%*', '%'))
197
203
  return "#{field.to_sql(operator, &block)} #{self.sql_operator(operator, field)} ?"
198
204
  elsif field.temporal?
@@ -339,11 +345,6 @@ module ScopedSearch
339
345
  # Defines the to_sql method for AST operator nodes
340
346
  module OperatorNode
341
347
 
342
- # Returns a NOT (...) SQL fragment that negates the current AST node's children
343
- def to_not_sql(builder, definition, &block)
344
- "NOT COALESCE(#{rhs.to_sql(builder, definition, &block)}, 0)"
345
- end
346
-
347
348
  # Returns an IS (NOT) NULL SQL fragment
348
349
  def to_null_sql(builder, definition, &block)
349
350
  field = definition.field_by_name(rhs.value)
@@ -387,7 +388,7 @@ module ScopedSearch
387
388
  # Convert this AST node to an SQL fragment.
388
389
  def to_sql(builder, definition, &block)
389
390
  if operator == :not && children.length == 1
390
- to_not_sql(builder, definition, &block)
391
+ builder.to_not_sql(rhs, definition, &block)
391
392
  elsif [:null, :notnull].include?(operator)
392
393
  to_null_sql(builder, definition, &block)
393
394
  elsif children.length == 1
@@ -447,12 +448,18 @@ module ScopedSearch
447
448
  # Switches out the default LIKE operator for ILIKE in the default
448
449
  # <tt>sql_operator</tt> method.
449
450
  def sql_operator(operator, field)
451
+ raise ScopedSearch::QueryNotSupported, "the operator '#{operator}' is not supported for field type '#{field.type}'" if [:like, :unlike].include?(operator) and !field.textual?
450
452
  case operator
451
- when :like then 'ILIKE'
452
- when :unlike then 'NOT ILIKE'
453
- else super(operator, field)
453
+ when :like then 'ILIKE'
454
+ when :unlike then 'NOT ILIKE'
455
+ else super(operator, field)
454
456
  end
455
457
  end
458
+
459
+ # Returns a NOT (...) SQL fragment that negates the current AST node's children
460
+ def to_not_sql(rhs, definition, &block)
461
+ "NOT COALESCE(#{rhs.to_sql(self, definition, &block)}, false)"
462
+ end
456
463
  end
457
464
 
458
465
  # The Oracle adapter also requires some tweaks to make the case insensitive LIKE work.
@@ -3,8 +3,8 @@ Gem::Specification.new do |s|
3
3
 
4
4
  # Do not change the version and date fields by hand. This will be done
5
5
  # automatically by the gem release script.
6
- s.version = "2.3.0"
7
- s.date = "2011-05-16"
6
+ s.version = "2.3.1"
7
+ s.date = "2011-06-22"
8
8
 
9
9
  s.summary = "Easily search you ActiveRecord models with a simple query language using a named scope."
10
10
  s.description = <<-EOS
@@ -34,7 +34,6 @@ ScopedSearch::RSpec::Database.test_databases.each do |db|
34
34
 
35
35
  after(:all) do
36
36
  ScopedSearch::RSpec::Database.drop_model(Foo)
37
- ScopedSearch::RSpec::Database.drop_model(Bar)
38
37
  ScopedSearch::RSpec::Database.close_connection
39
38
  end
40
39
 
@@ -48,15 +47,15 @@ ScopedSearch::RSpec::Database.test_databases.each do |db|
48
47
  end
49
48
 
50
49
  it "should complete the string comparators" do
51
- Foo.complete_for('string ').should =~ (["string != ", "string !~ ", "string = ", "string ~ "])
50
+ Foo.complete_for('string ').should =~ (["string != ", "string !~ ", "string = ", "string ~ "])
52
51
  end
53
52
 
54
53
  it "should complete the numerical comparators" do
55
- Foo.complete_for('int ').should =~ (["int != ", "int < ", "int <= ", "int = ", "int > ", "int >= "])
54
+ Foo.complete_for('int ').should =~ (["int != ", "int < ", "int <= ", "int = ", "int > ", "int >= "])
56
55
  end
57
56
 
58
57
  it "should complete the temporal (date) comparators" do
59
- Foo.complete_for('date ').should =~ (["date = ", "date < ", "date > "])
58
+ Foo.complete_for('date ').should =~ (["date = ", "date < ", "date > "])
60
59
  end
61
60
 
62
61
  it "should raise error for unindexed field" do
@@ -68,11 +67,11 @@ ScopedSearch::RSpec::Database.test_databases.each do |db|
68
67
  end
69
68
 
70
69
  it "should complete logical comparators" do
71
- Foo.complete_for('string ~ fo ').should contain("string ~ fo and", "string ~ fo or")
70
+ Foo.complete_for('string ~ fo ').should contain("string ~ fo and", "string ~ fo or")
72
71
  end
73
72
 
74
73
  it "should complete prefix operators" do
75
- Foo.complete_for(' ').should contain(" has", " not")
74
+ Foo.complete_for(' ').should contain(" has", " not")
76
75
  end
77
76
 
78
77
  it "should not complete logical infix operators" do
@@ -96,7 +95,7 @@ ScopedSearch::RSpec::Database.test_databases.each do |db|
96
95
  end
97
96
 
98
97
  it "should complete values should contain baz" do
99
- Foo.complete_for('explicit = ').should contain('explicit = baz')
98
+ Foo.complete_for('explicit = ').should contain('explicit = baz')
100
99
  end
101
100
  end
102
101
 
@@ -113,19 +112,19 @@ ScopedSearch::RSpec::Database.test_databases.each do |db|
113
112
  context 'using null prefix operators queries' do
114
113
 
115
114
  it "should complete has operator" do
116
- Foo.complete_for('has strin').should eql(['has string '])
115
+ Foo.complete_for('has strin').should eql(['has string '])
117
116
  end
118
117
 
119
118
  it "should complete null? operator" do
120
- Foo.complete_for('null? st').should eql(['null? string '])
119
+ Foo.complete_for('null? st').should eql(['null? string '])
121
120
  end
122
121
 
123
122
  it "should complete set? operator" do
124
- Foo.complete_for('set? exp').should eql(['set? explicit '])
123
+ Foo.complete_for('set? exp').should eql(['set? explicit '])
125
124
  end
126
125
 
127
126
  it "should complete null? operator for explicit field" do
128
- Foo.complete_for('null? explici').should eql(['null? explicit '])
127
+ Foo.complete_for('null? explici').should eql(['null? explicit '])
129
128
  end
130
129
 
131
130
  it "should not complete comparators after prefix statement" do
@@ -222,7 +222,6 @@ ScopedSearch::RSpec::Database.test_databases.each do |db|
222
222
 
223
223
  after(:all) do
224
224
  ScopedSearch::RSpec::Database.drop_model(@foo)
225
- @record.destroy
226
225
  end
227
226
 
228
227
  it "should not find any record because first equal = 2" do
data/spec/lib/database.rb CHANGED
@@ -17,7 +17,7 @@ module ScopedSearch::RSpec::Database
17
17
  end
18
18
 
19
19
  def self.test_databases
20
- test_databases_configuration.keys
20
+ test_databases_configuration.keys.sort
21
21
  end
22
22
 
23
23
  def self.establish_named_connection(name)
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scoped_search
3
3
  version: !ruby/object:Gem::Version
4
- hash: 3
5
- prerelease:
4
+ prerelease: false
6
5
  segments:
7
6
  - 2
8
7
  - 3
9
- - 0
10
- version: 2.3.0
8
+ - 1
9
+ version: 2.3.1
11
10
  platform: ruby
12
11
  authors:
13
12
  - Willem van Bergen
@@ -16,7 +15,7 @@ autorequire:
16
15
  bindir: bin
17
16
  cert_chain: []
18
17
 
19
- date: 2011-05-16 00:00:00 -04:00
18
+ date: 2011-06-22 00:00:00 -04:00
20
19
  default_executable:
21
20
  dependencies:
22
21
  - !ruby/object:Gem::Dependency
@@ -27,7 +26,6 @@ dependencies:
27
26
  requirements:
28
27
  - - ">="
29
28
  - !ruby/object:Gem::Version
30
- hash: 11
31
29
  segments:
32
30
  - 2
33
31
  - 1
@@ -43,7 +41,6 @@ dependencies:
43
41
  requirements:
44
42
  - - ~>
45
43
  - !ruby/object:Gem::Version
46
- hash: 3
47
44
  segments:
48
45
  - 2
49
46
  - 0
@@ -58,7 +55,6 @@ dependencies:
58
55
  requirements:
59
56
  - - ">="
60
57
  - !ruby/object:Gem::Version
61
- hash: 3
62
58
  segments:
63
59
  - 0
64
60
  version: "0"
@@ -131,7 +127,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
131
127
  requirements:
132
128
  - - ">="
133
129
  - !ruby/object:Gem::Version
134
- hash: 3
135
130
  segments:
136
131
  - 0
137
132
  version: "0"
@@ -140,14 +135,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
140
135
  requirements:
141
136
  - - ">="
142
137
  - !ruby/object:Gem::Version
143
- hash: 3
144
138
  segments:
145
139
  - 0
146
140
  version: "0"
147
141
  requirements: []
148
142
 
149
143
  rubyforge_project:
150
- rubygems_version: 1.6.2
144
+ rubygems_version: 1.3.7
151
145
  signing_key:
152
146
  specification_version: 3
153
147
  summary: Easily search you ActiveRecord models with a simple query language using a named scope.