scoped_search 4.1.4 → 4.1.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cf2c98d3eed66905e04497673572661d98ca832a
4
- data.tar.gz: 5cda23768c0ffef857dc038d74abd2539bf8881c
3
+ metadata.gz: 25198636d3a83a3be37b174722b43786bfb66c40
4
+ data.tar.gz: 2d51410c045dd98edffd782900a960f5111c47f4
5
5
  SHA512:
6
- metadata.gz: 96425ef732825dfb333d977f55a55be95ef3ac9dfda0ba9c4353fc97227d5caebfc4977b8cbdb786eb5929db84885f74435b7ca8795e449dcd2f7b432b0abbf5
7
- data.tar.gz: '068d65cd7fe9e1d4e58b0080d92a22a9216ed879e17275aec5bce2651ce6cced96251803f062113c6ab66135a3ae90e478cf7b90bd2ea7b0437f5f83a96516ce'
6
+ metadata.gz: 467be1c841cb5a0ce8eff10af66df07db0527a8b7423f386ad8a5ea29bea2ab4e3d02edb0b480ff427bfbdc0078ca1ac138690866db4fb67f13c31322334320b
7
+ data.tar.gz: fbc5a32d17479d8e919ca7b9e198416a0acb60bcbf0e1b2b3b7b850ad97af135a7cb5d57b0f93d3fee7a1b27c8ee7b47871367506ebe100e8beb58179041c01d
@@ -6,7 +6,11 @@ Please add an entry to the "Unreleased changes" section in your pull requests.
6
6
 
7
7
  === Unreleased changes
8
8
 
9
- *Nothing yet*
9
+ - Nothing yet
10
+
11
+ === Version 4.1.5
12
+
13
+ - Bugfix related to auto-completion of virtual fields (#182)
10
14
 
11
15
  === Version 4.1.4
12
16
 
@@ -270,7 +270,7 @@ module ScopedSearch
270
270
 
271
271
  # This method complete infix operators by field type
272
272
  def complete_operator(node)
273
- definition.operator_by_field_name(node.value)
273
+ definition.operator_by_field_name(node.value).map { |o| o.end_with?(' ') ? o : "#{o} " }
274
274
  end
275
275
  end
276
276
  end
@@ -107,6 +107,11 @@ module ScopedSearch
107
107
  end
108
108
  end
109
109
 
110
+ # Returns true if this is a virtual field.
111
+ def virtual?
112
+ !ext_method.nil?
113
+ end
114
+
110
115
  # Returns the ActiveRecord column definition that corresponds to this field.
111
116
  def column
112
117
  @column ||= begin
@@ -120,15 +125,15 @@ module ScopedSearch
120
125
 
121
126
  # Returns the column type of this field.
122
127
  def type
123
- @type ||= column.type
128
+ @type ||= virtual? ? :virtual : column.type
124
129
  end
125
130
 
126
- # Returns true if this field is a datetime-like column
131
+ # Returns true if this field is a datetime-like column.
127
132
  def datetime?
128
133
  [:datetime, :time, :timestamp].include?(type)
129
134
  end
130
135
 
131
- # Returns true if this field is a date-like column
136
+ # Returns true if this field is a date-like column.
132
137
  def date?
133
138
  type == :date
134
139
  end
@@ -167,7 +172,7 @@ module ScopedSearch
167
172
  return "#{field} #{order}"
168
173
  end
169
174
 
170
- # Return 'table'.'column' with the correct database quotes
175
+ # Return 'table'.'column' with the correct database quotes.
171
176
  def quoted_field
172
177
  c = klass.connection
173
178
  "#{c.quote_table_name(klass.table_name)}.#{c.quote_column_name(field)}"
@@ -231,11 +236,12 @@ module ScopedSearch
231
236
  def operator_by_field_name(name)
232
237
  field = field_by_name(name)
233
238
  return [] if field.nil?
234
- return field.operators if field.operators
235
- return ['= ', '!= '] if field.set?
236
- return ['= ', '> ', '< ', '<= ', '>= ','!= ', '^ ', '!^ '] if field.numerical?
237
- return ['= ', '!= ', '~ ', '!~ ', '^ ', '!^ '] if field.textual?
238
- return ['= ', '> ', '< '] if field.temporal?
239
+ return field.operators if field.operators
240
+ return ['=', '!=', '>', '<', '<=', '>=', '~', '!~', '^', '!^'] if field.virtual?
241
+ return ['=', '!='] if field.set?
242
+ return ['=', '>', '<', '<=', '>=', '!=', '^', '!^'] if field.numerical?
243
+ return ['=', '!=', '~', '!~', '^', '!^'] if field.textual?
244
+ return ['=', '>', '<'] if field.temporal?
239
245
  raise ScopedSearch::QueryNotSupported, "Unsupported type '#{field.type.inspect}')' for field '#{name}'. This can be a result of a search definition problem."
240
246
  end
241
247
 
@@ -245,7 +251,7 @@ module ScopedSearch
245
251
  # Returns a list of appropriate fields to search in given a search keyword and operator.
246
252
  def default_fields_for(value, operator = nil)
247
253
 
248
- column_types = []
254
+ column_types = [:virtual]
249
255
  column_types += [:string, :text] if [nil, :like, :unlike, :ne, :eq].include?(operator)
250
256
  column_types += [:double, :float, :decimal] if value =~ NUMERICAL_REGXP
251
257
  column_types += [:integer] if value =~ INTEGER_REGXP
@@ -113,7 +113,7 @@ module ScopedSearch
113
113
  # By default, it will simply look up the correct SQL operator in the SQL_OPERATORS
114
114
  # hash, but this can be overridden by a database adapter.
115
115
  def sql_operator(operator, field)
116
- raise ScopedSearch::QueryNotSupported, "the operator '#{operator}' is not supported for field type '#{field.type}'" if !field.ext_method and [:like, :unlike].include?(operator) and !field.textual?
116
+ raise ScopedSearch::QueryNotSupported, "the operator '#{operator}' is not supported for field type '#{field.type}'" if !field.virtual? and [:like, :unlike].include?(operator) and !field.textual?
117
117
  SQL_OPERATORS[operator]
118
118
  end
119
119
 
@@ -210,7 +210,7 @@ module ScopedSearch
210
210
  # <tt>operator</tt>:: The operator used for comparison.
211
211
  # <tt>value</tt>:: The value to compare the field with.
212
212
  def sql_test(field, operator, value, lhs, &block) # :yields: finder_option_type, value
213
- return field.to_ext_method_sql(lhs, sql_operator(operator, field), value, &block) if field.ext_method
213
+ return field.to_ext_method_sql(lhs, sql_operator(operator, field), value, &block) if field.virtual?
214
214
 
215
215
  yield(:keyparameter, lhs.sub(/^.*\./,'')) if field.key_field
216
216
 
@@ -403,7 +403,7 @@ module ScopedSearch
403
403
  def to_ext_method_sql(key, operator, value, &block)
404
404
  raise ScopedSearch::QueryNotSupported, "'#{definition.klass}' doesn't respond to '#{ext_method}'" unless definition.klass.respond_to?(ext_method)
405
405
  begin
406
- conditions = definition.klass.send(ext_method.to_sym, key, operator, value)
406
+ conditions = definition.klass.send(ext_method.to_sym, key, operator, value)
407
407
  rescue StandardError => e
408
408
  raise ScopedSearch::QueryNotSupported, "external method '#{ext_method}' failed with error: #{e}"
409
409
  end
@@ -554,7 +554,7 @@ module ScopedSearch
554
554
  # Switches out the default LIKE operator in the default <tt>sql_operator</tt>
555
555
  # method for ILIKE or @@ if full text searching is enabled.
556
556
  def sql_operator(operator, field)
557
- raise ScopedSearch::QueryNotSupported, "the operator '#{operator}' is not supported for field type '#{field.type}'" if !field.ext_method and [:like, :unlike].include?(operator) and !field.textual?
557
+ raise ScopedSearch::QueryNotSupported, "the operator '#{operator}' is not supported for field type '#{field.type}'" if !field.virtual? and [:like, :unlike].include?(operator) and !field.textual?
558
558
  return '@@' if [:like, :unlike].include?(operator) && field.full_text_search
559
559
  case operator
560
560
  when :like then 'ILIKE'
@@ -1,3 +1,3 @@
1
1
  module ScopedSearch
2
- VERSION = "4.1.4"
2
+ VERSION = "4.1.5"
3
3
  end
@@ -2,9 +2,11 @@ require "spec_helper"
2
2
 
3
3
  describe ScopedSearch::AutoCompleteBuilder do
4
4
 
5
+ let(:klass) { Class.new(ActiveRecord::Base) }
6
+
5
7
  before(:each) do
6
8
  @definition = double('ScopedSearch::Definition')
7
- @definition.stub(:klass).and_return(Class.new(ActiveRecord::Base))
9
+ @definition.stub(:klass).and_return(klass)
8
10
  @definition.stub(:profile).and_return(:default)
9
11
  @definition.stub(:profile=).and_return(true)
10
12
  end
@@ -17,4 +19,18 @@ describe ScopedSearch::AutoCompleteBuilder do
17
19
  ScopedSearch::AutoCompleteBuilder.auto_complete(@definition, "").should == []
18
20
  end
19
21
 
22
+ context "with ext_method" do
23
+ before do
24
+ @definition = ScopedSearch::Definition.new(klass)
25
+ @definition.define(:test_field, ext_method: :ext_test)
26
+ @definition.klass.stub(:connection).and_return(double())
27
+ @definition.klass.stub(:columns_hash).and_return({})
28
+ end
29
+
30
+ it "should support operator auto-completion on a virtual field" do
31
+ klass.should_receive(:ext_test).with('', '=', 'test_field').and_return(conditions: '')
32
+ ScopedSearch::AutoCompleteBuilder.auto_complete(@definition, 'test_field ').should eq(["test_field = ", "test_field != ", "test_field > ", "test_field < ", "test_field <= ", "test_field >= ", "test_field ~ ", "test_field !~ ", "test_field ^ ", "test_field !^ "])
33
+ end
34
+ end
35
+
20
36
  end
@@ -38,6 +38,7 @@ describe ScopedSearch::QueryBuilder do
38
38
 
39
39
  it "should validate value if validator selected" do
40
40
  field = double('field')
41
+ field.stub(:virtual?).and_return(false)
41
42
  field.stub(:only_explicit).and_return(true)
42
43
  field.stub(:field).and_return(:test_field)
43
44
  field.stub(:validator).and_return(->(_value) { false })
@@ -49,6 +50,7 @@ describe ScopedSearch::QueryBuilder do
49
50
 
50
51
  it "should validate value if validator selected" do
51
52
  field = double('field')
53
+ field.stub(:virtual?).and_return(false)
52
54
  field.stub(:only_explicit).and_return(true)
53
55
  field.stub(:field).and_return(:test_field)
54
56
  field.stub(:ext_method).and_return(nil)
@@ -65,6 +67,7 @@ describe ScopedSearch::QueryBuilder do
65
67
 
66
68
  it "should display custom error from validator" do
67
69
  field = double('field')
70
+ field.stub(:virtual?).and_return(false)
68
71
  field.stub(:only_explicit).and_return(true)
69
72
  field.stub(:field).and_return(:test_field)
70
73
  field.stub(:validator).and_return(->(_value) { raise ScopedSearch::QueryNotSupported, 'my custom message' })
@@ -90,7 +93,7 @@ describe ScopedSearch::QueryBuilder do
90
93
  ScopedSearch::QueryBuilder.build_query(@definition, 'test_field = test_val').should eq(include: ['test1'], joins: ['test2'])
91
94
  end
92
95
 
93
- it "should support LIKE query even if database field doesn't exist" do
96
+ it "should support LIKE query on a virtual field" do
94
97
  klass.should_receive(:ext_test).with('test_field', 'LIKE', 'test_val').and_return(conditions: 'field LIKE ?', parameter: ['%test_val%'])
95
98
  ScopedSearch::QueryBuilder.build_query(@definition, 'test_field ~ test_val').should eq(conditions: ['(field LIKE ?)', '%test_val%'])
96
99
  end
@@ -100,7 +103,7 @@ describe ScopedSearch::QueryBuilder do
100
103
  lambda { ScopedSearch::QueryBuilder.build_query(@definition, 'test_field = test_val') }.should raise_error(ScopedSearch::QueryNotSupported, /should return hash/)
101
104
  end
102
105
 
103
- it "should raise error when method doesn't exist" do
106
+ it "should raise error when ext_method doesn't exist" do
104
107
  lambda { ScopedSearch::QueryBuilder.build_query(@definition, 'test_field = test_val') }.should raise_error(ScopedSearch::QueryNotSupported, /doesn't respond to 'ext_test'/)
105
108
  end
106
109
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scoped_search
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.4
4
+ version: 4.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Amos Benari
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2018-09-06 00:00:00.000000000 Z
13
+ date: 2018-09-19 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
@@ -157,7 +157,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
157
157
  version: '0'
158
158
  requirements: []
159
159
  rubyforge_project:
160
- rubygems_version: 2.6.8
160
+ rubygems_version: 2.6.11
161
161
  signing_key:
162
162
  specification_version: 4
163
163
  summary: Easily search you ActiveRecord models with a simple query language using