scoped_search 2.6.5 → 2.7.0

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: 3bb6838588ce385873a180ec0e875deedde5fcde
4
- data.tar.gz: efbe17ef6dd34eadea7ac3251b3fbf5225e4e2c5
3
+ metadata.gz: 7053f29622ce510229c05ba561ce8a1e275942cf
4
+ data.tar.gz: e28a7d2541cc4e586b2bcbde23ea4742fa7a5671
5
5
  SHA512:
6
- metadata.gz: aa3ed52f60b294fba0ef10b2299882e820d985b26dd03dfdcb0c91b93fb2445c5fe21817e80a4d452eb5f169f68626f4a672e7abb8f7e542a94516a794bcd979
7
- data.tar.gz: c43a5e3d499f854bf01ae594387650bf46deaf4e4770ed44047949b2fcd0ca46bcd8ab8312970430fbe58ff9bebea86125a5862c9e840bde4821c94d960bfb05
6
+ metadata.gz: 7e3fac5a915408137d1ae6eb7194ddb43f75501407e13dd7203da779dc8e23fc011b0f55f2b7a1b6c461fb799e3afd376881bd001d6cc7276443d96ce8f2e7cd
7
+ data.tar.gz: 7b8643f0e611d089409b34f87f0102ef856ec9079d2f07e0ce1458ded6402f1d7c08d251ab4d609c29489e4eb5d5a673390e99948ce429eea663c3ef1638c85b
data/.gitignore CHANGED
@@ -8,5 +8,5 @@ scoped_search-*.gem
8
8
  /files
9
9
  /spec/database.yml
10
10
  .bundle/
11
- Gemfile.lock
11
+ Gemfile*.lock
12
12
  .idea/
data/.travis.yml CHANGED
@@ -5,28 +5,26 @@ before_script:
5
5
  - mysql -e 'create database scoped_search_test;'
6
6
  rvm:
7
7
  - 1.8.7
8
- - 1.9.2
9
8
  - 1.9.3
10
9
  - 2.0.0
10
+ - 2.1.1
11
11
  - ruby-head
12
- - ree
13
12
  - jruby-18mode
14
13
  - jruby-19mode
15
14
  - jruby-head
16
15
  gemfile:
17
16
  - Gemfile.activerecord2
18
17
  - Gemfile.activerecord3
18
+ - Gemfile.activerecord4
19
19
  matrix:
20
20
  include:
21
- - rvm: 1.9.3
22
- gemfile: Gemfile.activerecord4
23
- - rvm: 2.0.0
24
- gemfile: Gemfile.activerecord4
25
21
  allow_failures:
26
22
  - rvm: ruby-head
27
23
  - rvm: jruby-head
28
- - rvm: jruby-18mode
29
- - rvm: jruby-19mode
24
+ - rvm: 2.0.0
25
+ gemfile: Gemfile.activerecord2
26
+ - rvm: 2.1.1
27
+ gemfile: Gemfile.activerecord2
30
28
  exclude:
31
29
  - rvm: jruby-18mode
32
30
  gemfile: Gemfile.activerecord2
@@ -34,6 +32,7 @@ matrix:
34
32
  gemfile: Gemfile.activerecord2
35
33
  - rvm: jruby-head
36
34
  gemfile: Gemfile.activerecord2
37
- - rvm: jruby-head
38
- gemfile: Gemfile.activerecord2
39
- - rvm: ree
35
+ - rvm: 1.8.7
36
+ gemfile: Gemfile.activerecord4
37
+ - rvm: jruby-18mode
38
+ gemfile: Gemfile.activerecord4
data/lib/scoped_search.rb CHANGED
@@ -17,19 +17,23 @@ module ScopedSearch
17
17
  # <tt>ActiveRecord::Base.search_for</tt> named scope.
18
18
  module ClassMethods
19
19
 
20
+ def self.extended(base)
21
+ base.class_attribute :scoped_search_definition
22
+ end
23
+
20
24
  # Export the scoped_search method fo defining the search options.
21
25
  # This method will create a definition instance for the class if it does not yet exist,
22
26
  # and use the object as block argument and retun value.
23
27
  def scoped_search(*definitions)
24
- @scoped_search ||= ScopedSearch::Definition.new(self)
28
+ self.scoped_search_definition ||= ScopedSearch::Definition.new(self)
25
29
  definitions.each do |definition|
26
30
  if definition[:on].kind_of?(Array)
27
- definition[:on].each { |field| @scoped_search.define(definition.merge(:on => field)) }
31
+ definition[:on].each { |field| self.scoped_search_definition.define(definition.merge(:on => field)) }
28
32
  else
29
- @scoped_search.define(definition)
33
+ self.scoped_search_definition.define(definition)
30
34
  end
31
35
  end
32
- return @scoped_search
36
+ return self.scoped_search_definition
33
37
  end
34
38
  end
35
39
 
@@ -137,13 +137,13 @@ module ScopedSearch
137
137
  q.chomp!(quoted[1]) if quoted
138
138
  end
139
139
 
140
- # for doted field names compact the suggestions list to be one suggestion
140
+ # for dotted field names compact the suggestions list to be one suggestion
141
141
  # unless the user has typed the relation name entirely or the suggestion list
142
142
  # is short.
143
- if (suggestions.size > 10 && (tokens.empty? || !(tokens.last.to_s.include?('.')) ) && !(is_value))
144
- suggestions = suggestions.map {|s|
145
- (s.to_s.split('.')[0].end_with?(tokens.last)) ? s.to_s : s.to_s.split('.')[0]
146
- }
143
+ if (suggestions.size > 10 && (tokens.empty? || !tokens.last.to_s.include?('.')) && !is_value)
144
+ suggestions = suggestions.map do |s|
145
+ s.to_s.split('.')[0].end_with?(tokens.last.to_s) ? s.to_s : s.to_s.split('.')[0]
146
+ end
147
147
  end
148
148
 
149
149
  suggestions.uniq.map {|m| "#{q} #{m}"}
@@ -158,7 +158,7 @@ module ScopedSearch
158
158
  if (f[1].key_field)
159
159
  keywords += complete_key(f[0], f[1], tokens.last)
160
160
  else
161
- keywords << f[0].to_s+' '
161
+ keywords << f[0].to_s + ' '
162
162
  end
163
163
  end
164
164
  keywords.sort
@@ -182,11 +182,11 @@ module ScopedSearch
182
182
  # this method auto-completes values of fields that have a :complete_value marker
183
183
  def complete_value
184
184
  if last_token_is(COMPARISON_OPERATORS)
185
- token = tokens[tokens.size-2]
185
+ token = tokens[tokens.size - 2]
186
186
  val = ''
187
187
  else
188
- token = tokens[tokens.size-3]
189
- val = tokens[tokens.size-1]
188
+ token = tokens[tokens.size - 3]
189
+ val = tokens[tokens.size - 1]
190
190
  end
191
191
 
192
192
  field = definition.field_by_name(token)
@@ -234,13 +234,14 @@ module ScopedSearch
234
234
 
235
235
  # Registers the search_for named scope within the class that is used for searching.
236
236
  def register_named_scope! # :nodoc
237
+ definition = self
237
238
  if @klass.ancestors.include?(ActiveRecord::Base)
238
239
  case ActiveRecord::VERSION::MAJOR
239
240
  when 2
240
- @klass.named_scope(:search_for, lambda { |*args| ScopedSearch::QueryBuilder.build_query(self, args[0], args[1]) })
241
+ @klass.named_scope(:search_for, lambda { |*args| ScopedSearch::QueryBuilder.build_query(definition, args[0], args[1]) })
241
242
  when 3
242
243
  @klass.scope(:search_for, lambda { |*args|
243
- find_options = ScopedSearch::QueryBuilder.build_query(self, args[0], args[1])
244
+ find_options = ScopedSearch::QueryBuilder.build_query(definition, args[0], args[1])
244
245
  search_scope = @klass.scoped
245
246
  search_scope = search_scope.where(find_options[:conditions]) if find_options[:conditions]
246
247
  search_scope = search_scope.includes(find_options[:include]) if find_options[:include]
@@ -250,7 +251,7 @@ module ScopedSearch
250
251
  })
251
252
  when 4
252
253
  @klass.scope(:search_for, lambda { |*args|
253
- find_options = ScopedSearch::QueryBuilder.build_query(self, args[0], args[1])
254
+ find_options = ScopedSearch::QueryBuilder.build_query(definition, args[0], args[1])
254
255
  search_scope = @klass.all
255
256
  search_scope = search_scope.where(find_options[:conditions]) if find_options[:conditions]
256
257
  search_scope = search_scope.includes(find_options[:include]) if find_options[:include]
@@ -269,11 +270,13 @@ module ScopedSearch
269
270
 
270
271
  # Registers the complete_for method within the class that is used for searching.
271
272
  def register_complete_for! # :nodoc
272
- @klass.class_eval do
273
- def self.complete_for(query, options = {})
274
- ScopedSearch::AutoCompleteBuilder.auto_complete(@scoped_search , query, options)
275
- end
276
- end
273
+ @klass.extend(ScopedSearch::AutoCompleteClassMethods)
274
+ end
275
+ end
276
+
277
+ module AutoCompleteClassMethods
278
+ def complete_for(query, options = {})
279
+ ScopedSearch::AutoCompleteBuilder.auto_complete(scoped_search_definition, query, options)
277
280
  end
278
281
  end
279
282
  end
@@ -89,19 +89,20 @@ module ScopedSearch
89
89
  def order_by(order, &block)
90
90
  order ||= definition.default_order
91
91
  return nil if order.blank?
92
- field = definition.field_by_name(order.to_s.split(' ')[0])
93
- raise ScopedSearch::QueryNotSupported, "the field '#{order.to_s.split(' ')[0]}' in the order statement is not valid field for search" unless field
92
+ field_name, direction_name = order.to_s.split(/\s+/, 2)
93
+ field = definition.field_by_name(field_name)
94
+ raise ScopedSearch::QueryNotSupported, "the field '#{field_name}' in the order statement is not valid field for search" unless field
94
95
  sql = field.to_sql(&block)
95
- direction = (order.to_s.downcase.include?('desc')) ? " DESC" : " ASC"
96
+ direction = (!direction_name.nil? && direction_name.downcase.eql?('desc')) ? " DESC" : " ASC"
96
97
  order = sql + direction
97
98
 
98
99
  return order
99
100
  end
100
101
 
101
102
  # A hash that maps the operators of the query language with the corresponding SQL operator.
102
- SQL_OPERATORS = { :eq =>'=', :ne => '<>', :like => 'LIKE', :unlike => 'NOT LIKE',
103
- :gt => '>', :lt =>'<', :lte => '<=', :gte => '>=',
104
- :in => 'IN',:notin => 'NOT IN' }
103
+ SQL_OPERATORS = { :eq => '=', :ne => '<>', :like => 'LIKE', :unlike => 'NOT LIKE',
104
+ :gt => '>', :lt =>'<', :lte => '<=', :gte => '>=',
105
+ :in => 'IN', :notin => 'NOT IN' }
105
106
 
106
107
  # Return the SQL operator to use given an operator symbol and field definition.
107
108
  #
@@ -223,13 +224,14 @@ module ScopedSearch
223
224
  elsif field.definition.klass.reflections[field.relation].try(:macro) == :has_many
224
225
  value = value.to_i if field.offset
225
226
  yield(:parameter, value)
226
- primary_key = "#{field.definition.klass.quoted_table_name}.#{field.definition.klass.primary_key}"
227
+ connection = field.definition.klass.connection
228
+ primary_key = "#{connection.quote_table_name(field.definition.klass.table_name)}.#{connection.quote_column_name(field.definition.klass.primary_key)}"
227
229
  if field.definition.klass.reflections[field.relation].options.has_key?(:through)
228
230
  join = has_many_through_join(field)
229
231
  return "#{primary_key} IN (SELECT #{primary_key} FROM #{join} WHERE #{field.to_sql(operator, &block)} #{self.sql_operator(operator, field)} ? )"
230
232
  else
231
- foreign_key = field.reflection_keys(field.definition.klass.reflections[field.relation])[1]
232
- return "#{primary_key} IN (SELECT #{foreign_key} FROM #{field.klass.quoted_table_name} WHERE #{field.to_sql(operator, &block)} #{self.sql_operator(operator, field)} ? )"
233
+ foreign_key = connection.quote_column_name(field.reflection_keys(field.definition.klass.reflections[field.relation])[1])
234
+ return "#{primary_key} IN (SELECT #{foreign_key} FROM #{connection.quote_table_name(field.klass.table_name)} WHERE #{field.to_sql(operator, &block)} #{self.sql_operator(operator, field)} ? )"
233
235
  end
234
236
  else
235
237
  value = value.to_i if field.offset
@@ -241,23 +243,27 @@ module ScopedSearch
241
243
  def has_many_through_join(field)
242
244
  many_class = field.definition.klass
243
245
  through = many_class.reflections[field.relation].options[:through]
244
- #table names
246
+ connection = many_class.connection
247
+
248
+ # table names
245
249
  endpoint_table_name = field.klass.table_name
246
250
  many_table_name = many_class.table_name
247
251
  middle_table_name = many_class.reflections[through].klass.table_name
248
- #primary and foreign keys + optional condition for the many to middle join
252
+
253
+ # primary and foreign keys + optional condition for the many to middle join
249
254
  pk1, fk1 = field.reflection_keys(many_class.reflections[through])
250
255
  condition1 = field.reflection_conditions(field.klass.reflections[many_table_name.to_sym])
251
- #primary and foreign keys + optional condition for the endpoint to middle join
256
+
257
+ # primary and foreign keys + optional condition for the endpoint to middle join
252
258
  pk2, fk2 = field.reflection_keys(field.klass.reflections[middle_table_name.to_sym])
253
259
  condition2 = field.reflection_conditions(many_class.reflections[field.relation])
254
260
 
255
261
  <<-SQL
256
- #{many_table_name}
257
- INNER JOIN #{middle_table_name}
258
- ON #{many_table_name}.#{pk1} = #{middle_table_name}.#{fk1} #{condition1}
259
- INNER JOIN #{endpoint_table_name}
260
- ON #{middle_table_name}.#{fk2} = #{endpoint_table_name}.#{pk2} #{condition2}
262
+ #{connection.quote_table_name(many_table_name)}
263
+ INNER JOIN #{connection.quote_table_name(middle_table_name)}
264
+ ON #{connection.quote_table_name(many_table_name)}.#{connection.quote_column_name(pk1)} = #{connection.quote_table_name(middle_table_name)}.#{connection.quote_column_name(fk1)} #{condition1}
265
+ INNER JOIN #{connection.quote_table_name(endpoint_table_name)}
266
+ ON #{connection.quote_table_name(middle_table_name)}.#{connection.quote_column_name(fk2)} = #{connection.quote_table_name(endpoint_table_name)}.#{connection.quote_column_name(pk2)} #{condition2}
261
267
  SQL
262
268
  end
263
269
 
@@ -277,13 +283,13 @@ module ScopedSearch
277
283
  if key_relation
278
284
  yield(:joins, construct_join_sql(key_relation, num) )
279
285
  yield(:keycondition, "#{key_klass.table_name}_#{num}.#{connection.quote_column_name(key_field.to_s)} = ?")
280
- klass_table_name = relation ? "#{klass.table_name}_#{num}" : connection.quote_table_name(klass.table_name)
281
- return "#{klass_table_name}.#{connection.quote_column_name(field.to_s)}"
286
+ klass_table_name = relation ? "#{klass.table_name}_#{num}" : klass.table_name
287
+ return "#{connection.quote_table_name(klass_table_name)}.#{connection.quote_column_name(field.to_s)}"
282
288
  elsif key_field
283
289
  yield(:joins, construct_simple_join_sql(num))
284
290
  yield(:keycondition, "#{key_klass.table_name}_#{num}.#{connection.quote_column_name(key_field.to_s)} = ?")
285
- klass_table_name = relation ? "#{klass.table_name}_#{num}" : connection.quote_table_name(klass.table_name)
286
- return "#{klass_table_name}.#{connection.quote_column_name(field.to_s)}"
291
+ klass_table_name = relation ? "#{klass.table_name}_#{num}" : klass.table_name
292
+ return "#{connection.quote_table_name(klass_table_name)}.#{connection.quote_column_name(field.to_s)}"
287
293
  elsif relation
288
294
  yield(:include, relation)
289
295
  end
@@ -340,7 +346,7 @@ module ScopedSearch
340
346
  main_table = definition.klass.table_name
341
347
  main_table_pk, value_table_fk_main = reflection_keys(definition.klass.reflections[relation])
342
348
 
343
- join_sql = "\n INNER JOIN #{connection.quote_table_name(key_value_table)} #{key_value_table}_#{num} ON (#{connection.quote_table_name(main_table)}.#{main_table_pk} = #{key_value_table}_#{num}.#{value_table_fk_main})"
349
+ join_sql = "\n INNER JOIN #{connection.quote_table_name(key_value_table)} #{key_value_table}_#{num} ON (#{connection.quote_table_name(main_table)}.#{connection.quote_column_name(main_table_pk)} = #{key_value_table}_#{num}.#{connection.quote_column_name(value_table_fk_main)})"
344
350
  return join_sql
345
351
  end
346
352
 
@@ -7,11 +7,13 @@ module ScopedSearch
7
7
  #
8
8
  # sort @search, :by => :username
9
9
  # sort @search, :by => :created_at, :as => "Created"
10
+ # sort @search, :by => :created_at, :default => "DESC"
10
11
  #
11
12
  # This helper accepts the following options:
12
13
  #
13
14
  # * <tt>:by</tt> - the name of the named scope. This helper will prepend this value with "ascend_by_" and "descend_by_"
14
15
  # * <tt>:as</tt> - the text used in the link, defaults to whatever is passed to :by
16
+ # * <tt>:default</tt> - default sorting order, DESC or ASC
15
17
  def sort(field, options = {}, html_options = {})
16
18
 
17
19
  unless options[:as]
@@ -21,14 +23,20 @@ module ScopedSearch
21
23
 
22
24
  ascend = "#{field} ASC"
23
25
  descend = "#{field} DESC"
24
-
25
- ascending = params[:order] == ascend
26
- new_sort = ascending ? descend : ascend
27
26
  selected = [ascend, descend].include?(params[:order])
28
27
 
28
+ case params[:order]
29
+ when ascend
30
+ new_sort = descend
31
+ when descend
32
+ new_sort = ascend
33
+ else
34
+ new_sort = ["ASC", "DESC"].include?(options[:default]) ? "#{field} #{options[:default]}" : ascend
35
+ end
36
+
29
37
  if selected
30
38
  css_classes = html_options[:class] ? html_options[:class].split(" ") : []
31
- if ascending
39
+ if new_sort == ascend
32
40
  options[:as] = "&#9650;&nbsp;#{options[:as]}"
33
41
  css_classes << "ascending"
34
42
  else
@@ -1,3 +1,3 @@
1
1
  module ScopedSearch
2
- VERSION = "2.6.5"
2
+ VERSION = "2.7.0"
3
3
  end
@@ -1,15 +1,15 @@
1
1
  sqlite:
2
- adapter: "jdbcsqlite3"
2
+ adapter: jdbcsqlite3
3
3
  database: ":memory:"
4
4
 
5
5
  mysql:
6
- adapter: "jdbcmysql"
7
- host: "localhost"
8
- username: "root"
9
- database: "scoped_search_test"
6
+ adapter: jdbcmysql
7
+ host: localhost
8
+ username: root
9
+ database: scoped_search_test
10
10
 
11
11
  postgresql:
12
- adapter: "jdbcpostgresql"
13
- host: "localhost"
14
- username: "postgres"
15
- database: "scoped_search_test"
12
+ adapter: jdbcpostgresql
13
+ host: localhost
14
+ username: postgres
15
+ database: scoped_search_test
@@ -1,16 +1,18 @@
1
1
  sqlite:
2
- adapter: "sqlite3"
2
+ adapter: sqlite3
3
3
  database: ":memory:"
4
4
 
5
- # mysql:
6
- # adapter: "mysql2"
7
- # host: "127.0.0.1"
8
- # port: 13306
9
- # username: "root"
10
- # database: "scoped_search_test"
5
+ mysql:
6
+ adapter: mysql2
7
+ host: localhost
8
+ port: 3306
9
+ username: root
10
+ database: scoped_search_test
11
+ encoding: utf8
11
12
 
12
- # postgresql:
13
- # adapter: "postgresql"
14
- # host: "127.0.0.1"
15
- # port: 5432
16
- # database: "scoped_search_test"
13
+ postgresql:
14
+ adapter: postgresql
15
+ host: localhost
16
+ username: postgres
17
+ port: 5432
18
+ database: scoped_search_test
@@ -38,6 +38,9 @@ ScopedSearch::RSpec::Database.test_databases.each do |db|
38
38
  scoped_search :on => :related, :in => :bars, :rename => 'bars.related'.to_sym
39
39
  end
40
40
 
41
+ class ::Infoo < ::Foo
42
+ end
43
+
41
44
  @foo_1 = Foo.create!(:string => 'foo', :another => 'temp 1', :explicit => 'baz', :int => 9 , :date => 'February 8, 2011' , :unindexed => 10)
42
45
  Foo.create!(:string => 'bar', :another => 'temp 2', :explicit => 'baz', :int => 9 , :date => 'February 10, 2011', :unindexed => 10)
43
46
  Foo.create!(:string => 'baz', :another => nil, :explicit => nil , :int => nil, :date => nil , :unindexed => nil)
@@ -52,6 +55,7 @@ ScopedSearch::RSpec::Database.test_databases.each do |db|
52
55
 
53
56
  Object.send :remove_const, :Foo
54
57
  Object.send :remove_const, :Bar
58
+ Object.send :remove_const, :Infoo
55
59
 
56
60
  ScopedSearch::RSpec::Database.close_connection
57
61
  end
@@ -104,7 +108,12 @@ ScopedSearch::RSpec::Database.test_databases.each do |db|
104
108
  it "should not contain deprecated field in autocompleter" do
105
109
  Foo.complete_for(' ').should_not contain(" deprecated")
106
110
  end
111
+ end
107
112
 
113
+ context 'inherited auto completer' do
114
+ it "should complete the field name" do
115
+ Infoo.complete_for('str').should =~ ([' string '])
116
+ end
108
117
  end
109
118
 
110
119
  context 'using an aliased field' do
@@ -14,6 +14,26 @@ ScopedSearch::RSpec::Database.test_databases.each do |db|
14
14
  ScopedSearch::RSpec::Database.close_connection
15
15
  end
16
16
 
17
+ context 'querying a subclass' do
18
+ before do
19
+ ActiveRecord::Migration.create_table(:supers) { |t| t.string :name }
20
+ class Super < ActiveRecord::Base
21
+ scoped_search :on => :name
22
+ end
23
+ class Sub < Super; end
24
+
25
+ @super_record = Super.create!(:name => 'test')
26
+ end
27
+
28
+ after do
29
+ ScopedSearch::RSpec::Database.drop_model(Super)
30
+ end
31
+
32
+ it "should find records when searching the subclass" do
33
+ Sub.search_for('test').should have(1).item
34
+ end
35
+ end
36
+
17
37
  context 'querying a :belongs_to relation' do
18
38
 
19
39
  before do
@@ -9,15 +9,21 @@ ScopedSearch::RSpec::Database.test_databases.each do |db|
9
9
  before(:all) do
10
10
  ScopedSearch::RSpec::Database.establish_named_connection(db)
11
11
 
12
- @class = ScopedSearch::RSpec::Database.create_model(:string => :string, :another => :string, :explicit => :string) do |klass|
12
+ @class = ScopedSearch::RSpec::Database.create_model(
13
+ :string => :string,
14
+ :another => :string,
15
+ :explicit => :string,
16
+ :description => :string
17
+ ) do |klass|
13
18
  klass.scoped_search :on => :string
14
19
  klass.scoped_search :on => :another, :default_operator => :eq, :alias => :alias, :default_order => :desc
15
20
  klass.scoped_search :on => :explicit, :only_explicit => true
21
+ klass.scoped_search :on => :description
16
22
  end
17
23
 
18
- @class.create!(:string => 'foo', :another => 'temp 1', :explicit => 'baz')
19
- @class.create!(:string => 'bar', :another => 'temp 2', :explicit => 'baz')
20
- @class.create!(:string => 'baz', :another => nil, :explicit => nil)
24
+ @class.create!(:string => 'foo', :another => 'temp 1', :explicit => 'baz', :description => '1 - one')
25
+ @class.create!(:string => 'bar', :another => 'temp 2', :explicit => 'baz', :description => '2 - two')
26
+ @class.create!(:string => 'baz', :another => nil, :explicit => nil, :description => '3 - three')
21
27
  end
22
28
 
23
29
  after(:all) do
@@ -202,7 +208,15 @@ ScopedSearch::RSpec::Database.test_databases.each do |db|
202
208
  @class.search_for('',:order => 'string DESC').first.string.should eql('foo')
203
209
  end
204
210
 
205
- it "default order by another DESC" do
211
+ it "sort by description ASC" do
212
+ @class.search_for('',:order => 'description ASC').first.description.should eql('1 - one')
213
+ end
214
+
215
+ it "sort by description DESC" do
216
+ @class.search_for('',:order => 'description DESC').first.description.should eql('3 - three')
217
+ end
218
+
219
+ it "default order by another DESC" do
206
220
  @class.search_for('').first.string.should eql('bar')
207
221
  end
208
222
 
@@ -212,6 +226,10 @@ ScopedSearch::RSpec::Database.test_databases.each do |db|
212
226
 
213
227
  Set.new(distinct_search.map(&:explicit)).should == Set['baz', nil]
214
228
  end
229
+
230
+ it 'should order using symbol' do
231
+ @class.search_for('',:order => :string).first.string.should eql('bar')
232
+ end
215
233
  end
216
234
  end
217
235
  end
@@ -0,0 +1,73 @@
1
+ require "spec_helper"
2
+ require "scoped_search/rails_helper"
3
+
4
+ module ActionViewHelperStubs
5
+ def html_escape(str)
6
+ str
7
+ end
8
+
9
+ def tag_options(options)
10
+ ""
11
+ end
12
+ end
13
+
14
+ describe ScopedSearch::RailsHelper do
15
+ include ScopedSearch::RailsHelper
16
+ include ActionViewHelperStubs
17
+
18
+ let(:params) { HashWithIndifferentAccess.new(:controller => "resources", :action => "search") }
19
+
20
+ it "should generate a link with the order param set" do
21
+ should_receive(:url_for).with(
22
+ "controller" => "resources",
23
+ "action" => "search",
24
+ "order" => "field ASC"
25
+ ).and_return("/example")
26
+
27
+ sort("field")
28
+ end
29
+
30
+ it "should generate a link with order param set to alternative default sorting order" do
31
+ should_receive(:url_for).with(
32
+ "controller" => "resources",
33
+ "action" => "search",
34
+ "order" => "field DESC"
35
+ ).and_return("/example")
36
+
37
+ sort("field", :default => "DESC")
38
+ end
39
+
40
+ it "should generate a link with the order param inverted" do
41
+ should_receive(:url_for).with(
42
+ "controller" => "resources",
43
+ "action" => "search",
44
+ "order" => "field DESC"
45
+ ).and_return("/example")
46
+
47
+ params[:order] = "field ASC"
48
+ sort("field")
49
+ end
50
+
51
+ it "should generate a link with other parameters retained" do
52
+ should_receive(:url_for).with(
53
+ "controller" => "resources",
54
+ "action" => "search",
55
+ "walrus" => "unicorns",
56
+ "order" => "field ASC"
57
+ ).and_return("/example")
58
+
59
+ params[:walrus] = "unicorns"
60
+ sort("field")
61
+ end
62
+
63
+ it "should replace the current sorting order" do
64
+ should_receive(:url_for).with(
65
+ "controller" => "resources",
66
+ "action" => "search",
67
+ "order" => "other ASC"
68
+ ).and_return("/example")
69
+
70
+ params[:order] = "field ASC"
71
+ sort("other")
72
+ end
73
+ 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: 2.6.5
4
+ version: 2.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Amos Benari
@@ -10,48 +10,48 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2014-03-10 00:00:00.000000000 Z
13
+ date: 2014-03-22 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
17
17
  requirement: !ruby/object:Gem::Requirement
18
18
  requirements:
19
- - - '>='
19
+ - - ">="
20
20
  - !ruby/object:Gem::Version
21
21
  version: 2.1.0
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
- - - '>='
26
+ - - ">="
27
27
  - !ruby/object:Gem::Version
28
28
  version: 2.1.0
29
29
  - !ruby/object:Gem::Dependency
30
30
  name: rspec
31
31
  requirement: !ruby/object:Gem::Requirement
32
32
  requirements:
33
- - - ~>
33
+ - - "~>"
34
34
  - !ruby/object:Gem::Version
35
35
  version: '2.0'
36
36
  type: :development
37
37
  prerelease: false
38
38
  version_requirements: !ruby/object:Gem::Requirement
39
39
  requirements:
40
- - - ~>
40
+ - - "~>"
41
41
  - !ruby/object:Gem::Version
42
42
  version: '2.0'
43
43
  - !ruby/object:Gem::Dependency
44
44
  name: rake
45
45
  requirement: !ruby/object:Gem::Requirement
46
46
  requirements:
47
- - - '>='
47
+ - - ">="
48
48
  - !ruby/object:Gem::Version
49
49
  version: '0'
50
50
  type: :development
51
51
  prerelease: false
52
52
  version_requirements: !ruby/object:Gem::Requirement
53
53
  requirements:
54
- - - '>='
54
+ - - ">="
55
55
  - !ruby/object:Gem::Version
56
56
  version: '0'
57
57
  description: " Scoped search makes it easy to search your ActiveRecord-based models.\n
@@ -74,8 +74,8 @@ extensions: []
74
74
  extra_rdoc_files:
75
75
  - README.rdoc
76
76
  files:
77
- - .gitignore
78
- - .travis.yml
77
+ - ".gitignore"
78
+ - ".travis.yml"
79
79
  - Gemfile
80
80
  - Gemfile.activerecord2
81
81
  - Gemfile.activerecord3
@@ -120,33 +120,34 @@ files:
120
120
  - spec/unit/definition_spec.rb
121
121
  - spec/unit/parser_spec.rb
122
122
  - spec/unit/query_builder_spec.rb
123
+ - spec/unit/rails_helper_spec.rb
123
124
  - spec/unit/tokenizer_spec.rb
124
125
  homepage: https://github.com/wvanbergen/scoped_search/wiki
125
126
  licenses: []
126
127
  metadata: {}
127
128
  post_install_message:
128
129
  rdoc_options:
129
- - --title
130
+ - "--title"
130
131
  - scoped_search
131
- - --main
132
+ - "--main"
132
133
  - README.rdoc
133
- - --line-numbers
134
- - --inline-source
134
+ - "--line-numbers"
135
+ - "--inline-source"
135
136
  require_paths:
136
137
  - lib
137
138
  required_ruby_version: !ruby/object:Gem::Requirement
138
139
  requirements:
139
- - - '>='
140
+ - - ">="
140
141
  - !ruby/object:Gem::Version
141
142
  version: '0'
142
143
  required_rubygems_version: !ruby/object:Gem::Requirement
143
144
  requirements:
144
- - - '>='
145
+ - - ">="
145
146
  - !ruby/object:Gem::Version
146
147
  version: '0'
147
148
  requirements: []
148
149
  rubyforge_project:
149
- rubygems_version: 2.0.3
150
+ rubygems_version: 2.2.2
150
151
  signing_key:
151
152
  specification_version: 4
152
153
  summary: Easily search you ActiveRecord models with a simple query language using
@@ -171,4 +172,5 @@ test_files:
171
172
  - spec/unit/definition_spec.rb
172
173
  - spec/unit/parser_spec.rb
173
174
  - spec/unit/query_builder_spec.rb
175
+ - spec/unit/rails_helper_spec.rb
174
176
  - spec/unit/tokenizer_spec.rb