scoped_search 3.2.0 → 3.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fa5c8206f13488ac53e60199ef5a08fc825c8654
4
- data.tar.gz: ad9258a231663b704d4bc28728059c19f1846fb5
3
+ metadata.gz: f8e91bf7d864d576d7020bd56184d9ed7173e5c3
4
+ data.tar.gz: 502a182f6303fb040a4b3e77f54d984a85d54093
5
5
  SHA512:
6
- metadata.gz: d9201e227813757d3fb3cba025d2692ab946f74206912c95b5b04db74932b2a350a7323085084a99ee7560afb584de91eb5cd931cad515403662170486121c53
7
- data.tar.gz: 29db95daea73ad5e2f4fa789dec6029d685ae2360a36d2063d6c58004191e1e202e25ab16f38a98d6dce3d5eb1b8b1ca0e74838a91892927254a366f4f7fce1e
6
+ metadata.gz: ce108bace0ec727d852a4e0d9db9d330bab9d157a4dd985d0bb77e88eff186553462451beaee8fc532ac8d0b95361174b60772511ee7e1016be5c6f3640fe16e
7
+ data.tar.gz: c5dcd4e411820161628a61cf0485bf457121ba4ab8338f12d3723f83d8a2938bb1b85469eab096bce6f96f9b76bfb65af58723973de9d63f8e996692cfa4c3b4
@@ -176,11 +176,12 @@ module ScopedSearch
176
176
 
177
177
  field.key_klass
178
178
  .where(value_conditions(field_name, val))
179
- .select("DISTINCT #{field_name}")
179
+ .select(field_name)
180
180
  .limit(20)
181
181
  .map(&field.key_field)
182
182
  .compact
183
183
  .map { |f| "#{name}.#{f} " }
184
+ .uniq
184
185
  end
185
186
 
186
187
  # this method auto-completes values of fields that have a :complete_value marker
@@ -201,12 +202,13 @@ module ScopedSearch
201
202
  return complete_key_value(field, token, val) if field.key_field
202
203
 
203
204
  completer_scope(field)
204
- .where(value_conditions(field, val))
205
- .select("DISTINCT #{field.quoted_field}")
205
+ .where(value_conditions(field.quoted_field, val))
206
+ .select(field.quoted_field)
206
207
  .limit(20)
207
208
  .map(&field.field)
208
209
  .compact
209
210
  .map { |v| v.to_s =~ /\s/ ? "\"#{v}\"" : v }
211
+ .uniq
210
212
  end
211
213
 
212
214
  def completer_scope(field)
@@ -251,7 +253,7 @@ module ScopedSearch
251
253
  end
252
254
 
253
255
  query
254
- .where(value_conditions(field, val))
256
+ .where(value_conditions(field.quoted_field, val))
255
257
  .select("DISTINCT #{field.quoted_field}")
256
258
  .limit(20)
257
259
  .map(&field.field)
@@ -260,8 +262,8 @@ module ScopedSearch
260
262
  end
261
263
 
262
264
  # This method returns conditions for selecting completion from partial value
263
- def value_conditions(field, val)
264
- val.blank? ? nil : "CAST(#{field.quoted_field} as CHAR(50)) LIKE '#{val.gsub("'","''")}%'".tr_s('%*', '%')
265
+ def value_conditions(field_name, val)
266
+ val.blank? ? nil : "CAST(#{field_name} as CHAR(50)) LIKE '#{val.gsub("'","''")}%'".tr_s('%*', '%')
265
267
  end
266
268
 
267
269
  # This method complete infix operators by field type
@@ -250,7 +250,7 @@ module ScopedSearch
250
250
  def register_named_scope! # :nodoc
251
251
  definition = self
252
252
  @klass.scope(:search_for, proc { |query, options|
253
- search_scope = ActiveRecord::VERSION::MAJOR == 3 ? @klass.scoped : @klass
253
+ search_scope = ActiveRecord::VERSION::MAJOR == 3 ? @klass.scoped : (ActiveRecord::VERSION::MINOR < 1 ? @klass.where(nil) : @klass.all)
254
254
 
255
255
  find_options = ScopedSearch::QueryBuilder.build_query(definition, query || '', options || {})
256
256
  search_scope = search_scope.where(find_options[:conditions]) if find_options[:conditions]
@@ -83,17 +83,21 @@ module ScopedSearch
83
83
  return find_attributes
84
84
  end
85
85
 
86
- def order_by(order, &block)
86
+ def find_field_for_order_by(order, &block)
87
87
  order ||= definition.default_order
88
- return nil if order.blank?
88
+ return [nil, nil] if order.blank?
89
89
  field_name, direction_name = order.to_s.split(/\s+/, 2)
90
90
  field = definition.field_by_name(field_name)
91
91
  raise ScopedSearch::QueryNotSupported, "the field '#{field_name}' in the order statement is not valid field for search" unless field
92
+ return field, direction_name
93
+ end
94
+
95
+ def order_by(order, &block)
96
+ field, direction_name = find_field_for_order_by(order, &block)
97
+ return nil if field.nil?
92
98
  sql = field.to_sql(&block)
93
99
  direction = (!direction_name.nil? && direction_name.downcase.eql?('desc')) ? " DESC" : " ASC"
94
- order = sql + direction
95
-
96
- return order
100
+ return sql + direction
97
101
  end
98
102
 
99
103
  # A hash that maps the operators of the query language with the corresponding SQL operator.
@@ -516,7 +520,10 @@ module ScopedSearch
516
520
 
517
521
  def order_by(order, &block)
518
522
  sql = super(order, &block)
519
- sql += sql.include?('DESC') ? ' NULLS LAST ' : ' NULLS FIRST ' if sql
523
+ if sql
524
+ field, _ = find_field_for_order_by(order, &block)
525
+ sql += sql.include?('DESC') ? ' NULLS LAST ' : ' NULLS FIRST ' if !field.nil? && field.column.null
526
+ end
520
527
  sql
521
528
  end
522
529
  end
@@ -22,7 +22,7 @@ module ScopedSearch
22
22
 
23
23
  ascend = "#{field} ASC"
24
24
  descend = "#{field} DESC"
25
- selected = [ascend, descend].include?(params[:order])
25
+ selected_sort = [ascend, descend].find { |o| o == params[:order] }
26
26
 
27
27
  case params[:order]
28
28
  when ascend
@@ -33,9 +33,9 @@ module ScopedSearch
33
33
  new_sort = ["ASC", "DESC"].include?(options[:default]) ? "#{field} #{options[:default]}" : ascend
34
34
  end
35
35
 
36
- if selected
36
+ unless selected_sort.nil?
37
37
  css_classes = html_options[:class] ? html_options[:class].split(" ") : []
38
- if new_sort == ascend
38
+ if selected_sort == ascend
39
39
  options[:as] = "&#9650;&nbsp;#{options[:as]}"
40
40
  css_classes << "ascending"
41
41
  else
@@ -1,3 +1,3 @@
1
1
  module ScopedSearch
2
- VERSION = "3.2.0"
2
+ VERSION = "3.2.1"
3
3
  end
@@ -89,6 +89,10 @@ ScopedSearch::RSpec::Database.test_databases.each do |db|
89
89
  Foo.complete_for('date ').should =~ (["date = ", "date < ", "date > "])
90
90
  end
91
91
 
92
+ it "should complete when query is already distinct" do
93
+ Foo.uniq.complete_for('int =').length.should > 0
94
+ end
95
+
92
96
  it "should raise error for unindexed field" do
93
97
  lambda { Foo.complete_for('unindexed = 10 ')}.should raise_error(ScopedSearch::QueryNotSupported)
94
98
  end
@@ -91,6 +91,10 @@ require "spec_helper"
91
91
  Item.complete_for('facts.').length.should == 2
92
92
  end
93
93
 
94
+ it "should complete facts names with partial name" do
95
+ Item.complete_for('facts.c').length.should == 1
96
+ end
97
+
94
98
  it "should complete values for fact name = color" do
95
99
  Item.complete_for('facts.color = ').length.should == 2
96
100
  end
@@ -31,6 +31,51 @@ ScopedSearch::RSpec::Database.test_databases.each do |db|
31
31
  ScopedSearch::RSpec::Database.close_connection
32
32
  end
33
33
 
34
+ context 'with no scoped_search defaults' do
35
+
36
+ before(:all) do
37
+ @class2 = ScopedSearch::RSpec::Database.create_model(
38
+ :string => :string,
39
+ :another => :string,
40
+ ) do |klass|
41
+ klass.scoped_search :on => :string
42
+ klass.scoped_search :on => :another
43
+ end
44
+
45
+ @class2.create!(:string => 'foo', :another => 'foo')
46
+ @class2.create!(:string => 'bar', :another => 'foo')
47
+ @class2.create!(:string => 'baz', :another => 'bar')
48
+ end
49
+
50
+ after(:all) do
51
+ ScopedSearch::RSpec::Database.drop_model(@class2)
52
+ end
53
+
54
+ context '#search_for with an empty string' do
55
+
56
+ it 'should not remove previous scope' do
57
+ @class2.where(another: 'foo').search_for('').count.should == 2
58
+ end
59
+
60
+ it 'should return an ActiveRecord::Relation' do
61
+ @class2.search_for('').should be_a(ActiveRecord::Relation)
62
+ end
63
+
64
+ end
65
+
66
+ context '#search_for with nil' do
67
+ it 'should not remove previous scope' do
68
+ @class2.where(another: 'foo').search_for(nil).count.should == 2
69
+ end
70
+
71
+ it 'should return an ActiveRecord::Relation' do
72
+ @class2.search_for(nil).should be_a(ActiveRecord::Relation)
73
+ end
74
+
75
+ end
76
+
77
+ end
78
+
34
79
  context 'in an implicit string field' do
35
80
  it "should find the record with an exact string match" do
36
81
  @class.search_for('foo').length.should == 1
@@ -70,4 +70,26 @@ describe ScopedSearch::RailsHelper do
70
70
  params[:order] = "field ASC"
71
71
  sort("other")
72
72
  end
73
+
74
+ it "should add no styling by default" do
75
+ should_receive(:url_for)
76
+ should_receive(:a_link).with('Field', anything, hash_excluding(:class))
77
+ sort("field")
78
+ end
79
+
80
+ it "should add ascending style for current ascending sort order " do
81
+ should_receive(:url_for)
82
+ should_receive(:a_link).with('&#9650;&nbsp;Field', anything, hash_including(:class => 'ascending'))
83
+
84
+ params[:order] = "field ASC"
85
+ sort("field")
86
+ end
87
+
88
+ it "should add descending style for current descending sort order " do
89
+ should_receive(:url_for)
90
+ should_receive(:a_link).with('&#9660;&nbsp;Field', anything, hash_including(:class => 'descending'))
91
+
92
+ params[:order] = "field DESC"
93
+ sort("field")
94
+ end
73
95
  end
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: 3.2.0
4
+ version: 3.2.1
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: 2015-02-23 00:00:00.000000000 Z
13
+ date: 2015-06-23 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord