ransack 0.7.2 → 1.0.0

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.
@@ -23,7 +23,12 @@ module Ransack
23
23
  module_function
24
24
  # replace % \ to \% \\
25
25
  def escape_wildcards(unescaped)
26
- unescaped.gsub(/\\/){ "\\\\" }.gsub(/%/, "\\%")
26
+ if ActiveRecord::VERSION::MAJOR == 3
27
+ unescaped.to_s.gsub(/([\\|\%|.])/, '\\\\\\1')
28
+ else
29
+ unescaped.to_s.gsub(/\\/){ "\\\\" }.gsub(/%/, "\\%")
30
+ end
27
31
  end
32
+
28
33
  end
29
34
  end
@@ -28,7 +28,7 @@ module Ransack
28
28
  end
29
29
 
30
30
  def initialize(object, options = {})
31
- @object = object.scoped
31
+ @object = relation_for(object)
32
32
  @klass = @object.klass
33
33
  @join_dependency = join_dependency(@object)
34
34
  @join_type = options[:join_type] || Arel::OuterJoin
@@ -44,6 +44,20 @@ module Ransack
44
44
  end
45
45
  end
46
46
 
47
+ def klassify(obj)
48
+ if Class === obj && ::ActiveRecord::Base > obj
49
+ obj
50
+ elsif obj.respond_to? :klass
51
+ obj.klass
52
+ elsif obj.respond_to? :active_record # Rails 3
53
+ obj.active_record
54
+ elsif obj.respond_to? :base_klass # Rails 4
55
+ obj.base_klass
56
+ else
57
+ raise ArgumentError, "Don't know how to klassify #{obj}"
58
+ end
59
+ end
60
+
47
61
  # Convert a string representing a chain of associations and an attribute
48
62
  # into the attribute itself
49
63
  def contextualize(str)
@@ -163,7 +163,8 @@ module Ransack
163
163
  end
164
164
  else
165
165
  [obj]
166
- end).compact.flatten.map {|v| [prefix, v].compact.join('_')}
166
+ end).
167
+ compact.flatten.map { |v| [prefix, v].compact.join('_') }
167
168
  end
168
169
 
169
170
  def attr_from_base_and_column(base, column)
@@ -59,11 +59,12 @@ module Ransack
59
59
  query_hash = {}
60
60
  query_hash[search.context.search_key] = search_params.merge(:s => "#{attr_name} #{new_dir}")
61
61
  options.merge!(query_hash)
62
+ options_for_url = params.merge options
62
63
 
63
64
  url = if routing_proxy && respond_to?(routing_proxy)
64
- send(routing_proxy).url_for(options)
65
+ send(routing_proxy).url_for(options_for_url)
65
66
  else
66
- url_for(options)
67
+ url_for(options_for_url)
67
68
  end
68
69
 
69
70
  link_to [ERB::Util.h(name), order_indicator_for(current_dir)].compact.join(' ').html_safe,
@@ -29,7 +29,7 @@ es:
29
29
  lt: "menor que"
30
30
  lt_any: "menor que cualquier"
31
31
  lt_all: "menor o igual a"
32
- lteq: "less than or equal to"
32
+ lteq: "menor que o igual a"
33
33
  lteq_any: "menor o igual a cualquier"
34
34
  lteq_all: "menor o igual a todos"
35
35
  gt: "mayor que"
@@ -0,0 +1,70 @@
1
+ fr:
2
+ ransack:
3
+ search: "recherche"
4
+ predicate: "prédicat"
5
+ and: "et"
6
+ or: "ou"
7
+ any: "au moins un"
8
+ all: "tous"
9
+ combinator: "combinateur"
10
+ attribute: "attribut"
11
+ value: "valeur"
12
+ condition: "condition"
13
+ sort: "tri"
14
+ asc: "ascendant"
15
+ desc: "descendant"
16
+ predicates:
17
+ eq: "égal à"
18
+ eq_any: "égal à au moins un"
19
+ eq_all: "égal à tous"
20
+ not_eq: "différent de"
21
+ not_eq_any: "différent d'au moins un"
22
+ not_eq_all: "différent de tous"
23
+ matches: "correspond à"
24
+ matches_any: "correspond à au moins un"
25
+ matches_all: "correspond à tous"
26
+ does_not_match: "ne correspond pas à"
27
+ does_not_match_any: "ne correspond pas à au moins un"
28
+ does_not_match_all: "ne correspond à aucun"
29
+ lt: "inférieur à"
30
+ lt_any: "inférieur à au moins un"
31
+ lt_all: "inférieur à tous"
32
+ lteq: "inférieur ou égal à"
33
+ lteq_any: "inférieur ou égal à au moins un"
34
+ lteq_all: "inférieur ou égal à tous"
35
+ gt: "supérieur à"
36
+ gt_any: "supérieur à au moins un"
37
+ gt_all: "supérieur à tous"
38
+ gteq: "supérieur ou égal à"
39
+ gteq_any: "supérieur ou égal à au moins un"
40
+ gteq_all: "supérieur ou égal à tous"
41
+ in: "inclus dans"
42
+ in_any: "inclus dans au moins un"
43
+ in_all: "inclus dans tous"
44
+ not_in: "non inclus dans"
45
+ not_in_any: "non inclus dans au moins un"
46
+ not_in_all: "non inclus dans tous"
47
+ cont: "contient"
48
+ cont_any: "contient au moins un"
49
+ cont_all: "contient tous"
50
+ not_cont: "ne contient pas"
51
+ not_cont_any: "ne contient pas au moins un"
52
+ not_cont_all: "ne contient pas tous"
53
+ start: "commence par"
54
+ start_any: "commence par au moins un"
55
+ start_all: "commence par tous"
56
+ not_start: "ne commence pas par"
57
+ not_start_any: "ne commence pas par au moins un"
58
+ not_start_all: "ne commence pas par tous"
59
+ end: "finit par"
60
+ end_any: "finit par au moins un"
61
+ end_all: "finit par tous"
62
+ not_end: "ne finit pas par"
63
+ not_end_any: "ne finit pas par au moins un"
64
+ not_end_all: "ne finit pas par tous"
65
+ 'true': "est vrai"
66
+ 'false': "est faux"
67
+ present: "est présent"
68
+ blank: "est blanc"
69
+ 'null': "est null"
70
+ not_null: "n'est pas null"
@@ -23,7 +23,7 @@ module Ransack
23
23
  attribute_names = attributes_str.split(/_and_|_or_/)
24
24
  combinator = attributes_str.match(/_and_/) ? :and : :or
25
25
  defaults = base_ancestors.map do |klass|
26
- :"ransack.attributes.#{klass.model_name.underscore}.#{original_name}"
26
+ :"ransack.attributes.#{klass.model_name.singular}.#{original_name}"
27
27
  end
28
28
 
29
29
  translated_names = attribute_names.map do |attr|
@@ -50,7 +50,7 @@ module Ransack
50
50
  raise ArgumentError, "A context is required to translate associations"
51
51
  end
52
52
 
53
- defaults = key.blank? ? [:"#{context.klass.i18n_scope}.models.#{context.klass.model_name.underscore}"] : [:"ransack.associations.#{context.klass.model_name.underscore}.#{key}"]
53
+ defaults = key.blank? ? [:"#{context.klass.i18n_scope}.models.#{context.klass.model_name.singular}"] : [:"ransack.associations.#{context.klass.model_name.singular}.#{key}"]
54
54
  defaults << context.traverse(key).model_name.human
55
55
  options = {:count => 1, :default => defaults}
56
56
  I18n.translate(defaults.shift, options)
@@ -65,19 +65,20 @@ module Ransack
65
65
  interpolations = {}
66
66
  interpolations[:attr_fallback_name] = I18n.translate(
67
67
  (associated_class ?
68
- :"ransack.attributes.#{associated_class.model_name.underscore}.#{attr_name}" :
69
- :"ransack.attributes.#{context.klass.model_name.underscore}.#{attr_name}"
68
+ :"ransack.attributes.#{associated_class.model_name.singular}.#{attr_name}" :
69
+ :"ransack.attributes.#{context.klass.model_name.singular}.#{attr_name}"
70
70
  ),
71
71
  :default => [
72
72
  (associated_class ?
73
- :"#{associated_class.i18n_scope}.attributes.#{associated_class.model_name.underscore}.#{attr_name}" :
74
- :"#{context.klass.i18n_scope}.attributes.#{context.klass.model_name.underscore}.#{attr_name}"
73
+ :"#{associated_class.i18n_scope}.attributes.#{associated_class.model_name.singular}.#{attr_name}" :
74
+ :"#{context.klass.i18n_scope}.attributes.#{context.klass.model_name.singular}.#{attr_name}"
75
75
  ),
76
+ :".attributes.#{attr_name}",
76
77
  attr_name.humanize
77
78
  ]
78
79
  )
79
80
  defaults = [
80
- :"ransack.attributes.#{context.klass.model_name.underscore}.#{name}"
81
+ :"ransack.attributes.#{context.klass.model_name.singular}.#{name}"
81
82
  ]
82
83
  if include_associations && associated_class
83
84
  defaults << '%{association_name} %{attr_fallback_name}'
@@ -89,4 +90,4 @@ module Ransack
89
90
  I18n.translate(defaults.shift, options.merge(interpolations))
90
91
  end
91
92
  end
92
- end
93
+ end
@@ -1,3 +1,3 @@
1
1
  module Ransack
2
- VERSION = "0.7.2"
2
+ VERSION = "1.0.0"
3
3
  end
data/ransack.gemspec CHANGED
@@ -14,9 +14,9 @@ Gem::Specification.new do |s|
14
14
 
15
15
  s.rubyforge_project = "ransack"
16
16
 
17
- s.add_dependency 'activerecord', '~> 3.0'
18
- s.add_dependency 'actionpack', '~> 3.0'
19
- s.add_dependency 'polyamorous', '~> 0.5.0'
17
+ s.add_dependency 'activerecord', '>= 3.0'
18
+ s.add_dependency 'actionpack', '>= 3.0'
19
+ s.add_dependency 'polyamorous', '~> 0.6.0'
20
20
  s.add_development_dependency 'rspec', '~> 2.8.0'
21
21
  s.add_development_dependency 'machinist', '~> 1.0.6'
22
22
  s.add_development_dependency 'faker', '~> 0.9.5'
@@ -6,6 +6,12 @@ module Ransack
6
6
  describe Context do
7
7
  subject { Context.new(Person) }
8
8
 
9
+ describe '#relation_for' do
10
+ it 'returns relation for given object' do
11
+ subject.object.should be_an ::ActiveRecord::Relation
12
+ end
13
+ end
14
+
9
15
  describe '#evaluate' do
10
16
  it 'evaluates search obects' do
11
17
  search = Search.new(Person, :name_eq => 'Joe Blow')
@@ -7,7 +7,7 @@ module Ransack
7
7
  router = ActionDispatch::Routing::RouteSet.new
8
8
  router.draw do
9
9
  resources :people
10
- match ':controller(/:action(/:id(.:format)))'
10
+ get ':controller(/:action(/:id(.:format)))'
11
11
  end
12
12
 
13
13
  include router.url_helpers
@@ -48,11 +48,21 @@ module Ransack
48
48
  end
49
49
 
50
50
  describe '#sort_link' do
51
- subject { @f.sort_link :name, :controller => 'people' }
51
+ it 'sort_link for ransack attribute' do
52
+ sort_link = @f.sort_link :name, :controller => 'people'
53
+ if ActiveRecord::VERSION::STRING =~ /^3\.[1-2]\./
54
+ sort_link.should match /people\?q%5Bs%5D=name\+asc/
55
+ else
56
+ sort_link.should match /people\?q(%5B|\[)s(%5D|\])=name\+asc/
57
+ end
58
+ sort_link.should match /sort_link/
59
+ sort_link.should match /Full Name<\/a>/
60
+ end
52
61
 
53
- it { should match /people\?q%5Bs%5D=name\+asc/}
54
- it { should match /sort_link/}
55
- it { should match /Full Name<\/a>/}
62
+ it 'sort_link for common attribute' do
63
+ sort_link = @f.sort_link :id, :controller => 'people'
64
+ sort_link.should match /id<\/a>/
65
+ end
56
66
  end
57
67
 
58
68
  describe '#submit' do
@@ -124,4 +134,4 @@ module Ransack
124
134
  end
125
135
  end
126
136
  end
127
- end
137
+ end
@@ -7,7 +7,7 @@ module Ransack
7
7
  router = ActionDispatch::Routing::RouteSet.new
8
8
  router.draw do
9
9
  resources :people
10
- match ':controller(/:action(/:id(.:format)))'
10
+ get ':controller(/:action(/:id(.:format)))'
11
11
  end
12
12
 
13
13
  include router.url_helpers
@@ -26,24 +26,71 @@ module Ransack
26
26
  end
27
27
 
28
28
  describe '#sort_link with default search_key' do
29
- subject { @controller.view_context.sort_link([:main_app, Person.search(:sorts => ['name desc'])], :name, :controller => 'people') }
30
- it { should match /people\?q%5Bs%5D=name\+asc/ }
29
+ subject {
30
+ @controller.view_context.sort_link(
31
+ [:main_app, Person.search(:sorts => ['name desc'])],
32
+ :name, :controller => 'people'
33
+ )
34
+ }
35
+ it { should match(
36
+ if ActiveRecord::VERSION::STRING =~ /^3\.[1-2]\./
37
+ /people\?q%5Bs%5D=name\+asc/
38
+ else
39
+ /people\?q(%5B|\[)s(%5D|\])=name\+asc/
40
+ end)
41
+ }
31
42
  it { should match /sort_link desc/ }
32
43
  it { should match /Full Name &#9660;/ }
33
44
  end
34
45
 
35
46
  describe '#sort_link with default search_key defined as symbol' do
36
- subject { @controller.view_context.sort_link(Person.search({:sorts => ['name desc']}, :search_key => :people_search),
37
- :name, :controller => 'people') }
38
-
39
- it { should match /people\?people_search%5Bs%5D=name\+asc/ }
47
+ subject { @controller.
48
+ view_context.sort_link(
49
+ Person.search({ :sorts => ['name desc'] }, :search_key => :people_search),
50
+ :name, :controller => 'people'
51
+ )
52
+ }
53
+ it { should match(
54
+ if ActiveRecord::VERSION::STRING =~ /^3\.[1-2]\./
55
+ /people\?people_search%5Bs%5D=name\+asc/
56
+ else
57
+ /people\?people_search(%5B|\[)s(%5D|\])=name\+asc/
58
+ end)
59
+ }
40
60
  end
41
61
 
42
62
  describe '#sort_link with default search_key defined as string' do
43
- subject { @controller.view_context.sort_link(Person.search({:sorts => ['name desc']}, :search_key => 'people_search'),
44
- :name, :controller => 'people') }
63
+ subject {
64
+ @controller.view_context.sort_link(
65
+ Person.search({ :sorts => ['name desc'] }, :search_key => 'people_search'),
66
+ :name, :controller => 'people'
67
+ )
68
+ }
69
+ it { should match(
70
+ if ActiveRecord::VERSION::STRING =~ /^3\.[1-2]\./
71
+ /people\?people_search%5Bs%5D=name\+asc/
72
+ else
73
+ /people\?people_search(%5B|\[)s(%5D|\])=name\+asc/
74
+ end)
75
+ }
76
+ end
77
+
45
78
 
46
- it { should match /people\?people_search%5Bs%5D=name\+asc/ }
79
+ context 'view has existing parameters' do
80
+ before do
81
+ @controller.view_context.params.merge!({ :exist => 'existing' })
82
+ end
83
+ describe '#sort_link should not remove existing params' do
84
+ subject {
85
+ @controller.view_context.sort_link(
86
+ Person.search({ :sorts => ['name desc'] }, :search_key => 'people_search'),
87
+ :name, :controller => 'people'
88
+ )
89
+ }
90
+ it {
91
+ should match /exist\=existing/
92
+ }
93
+ end
47
94
  end
48
95
  end
49
96
  end
@@ -7,6 +7,24 @@ module Ransack
7
7
  @s = Search.new(Person)
8
8
  end
9
9
 
10
+ shared_examples 'wildcard escaping' do |method, regexp|
11
+ it 'automatically converts integers to strings' do
12
+ subject.parent_id_cont = 1
13
+ expect { subject.result }.to_not raise_error
14
+ end
15
+
16
+ it (
17
+ if ActiveRecord::VERSION::MAJOR == 3
18
+ "escapes '%', '.' and '\\\\' in value"
19
+ else
20
+ "escapes % and \\ in value"
21
+ end
22
+ ) do
23
+ subject.send(:"#{method}=", '%._\\')
24
+ subject.result.to_sql.should match(regexp)
25
+ end
26
+ end
27
+
10
28
  describe 'eq' do
11
29
  it 'generates an equality condition for boolean true' do
12
30
  @s.awesome_eq = true
@@ -25,17 +43,32 @@ module Ransack
25
43
  end
26
44
 
27
45
  describe 'cont' do
46
+
47
+ it_has_behavior 'wildcard escaping', :name_cont, (
48
+ if ActiveRecord::VERSION::MAJOR == 3
49
+ /"people"."name" LIKE '%\\%\\._\\\\%'/
50
+ else
51
+ /"people"."name" LIKE '%\\%._\\\\%'/
52
+ end) do
53
+ subject { @s }
54
+ end
55
+
28
56
  it 'generates a LIKE query with value surrounded by %' do
29
57
  @s.name_cont = 'ric'
30
58
  @s.result.to_sql.should match /"people"."name" LIKE '%ric%'/
31
59
  end
32
- it 'escapes %, _ and \\ in value' do
33
- @s.name_cont = '%_\\'
34
- @s.result.to_sql.should match /"people"."name" LIKE '%\\%\\_\\\\%'/
35
- end
36
60
  end
37
61
 
38
62
  describe 'not_cont' do
63
+ it_has_behavior 'wildcard escaping', :name_not_cont, (
64
+ if ActiveRecord::VERSION::MAJOR == 3
65
+ /"people"."name" NOT LIKE '%\\%\\._\\\\%'/
66
+ else
67
+ /"people"."name" NOT LIKE '%\\%._\\\\%'/
68
+ end) do
69
+ subject { @s }
70
+ end
71
+
39
72
  it 'generates a NOT LIKE query with value surrounded by %' do
40
73
  @s.name_not_cont = 'ric'
41
74
  @s.result.to_sql.should match /"people"."name" NOT LIKE '%ric%'/
@@ -32,8 +32,10 @@ module Ransack
32
32
  end
33
33
 
34
34
  it 'creates Conditions for multiple polymorphic belongs_to association attributes' do
35
- search = Search.new(Note, :notable_of_Person_type_name_or_notable_of_Article_type_title_eq => 'Ernie')
36
- condition = search.base[:notable_of_Person_type_name_or_notable_of_Article_type_title_eq]
35
+ search = Search.new(Note,
36
+ :notable_of_Person_type_name_or_notable_of_Article_type_title_eq => 'Ernie')
37
+ condition = search.
38
+ base[:notable_of_Person_type_name_or_notable_of_Article_type_title_eq]
37
39
  condition.should be_a Nodes::Condition
38
40
  condition.predicate.name.should eq 'eq'
39
41
  condition.attributes.first.name.should eq 'notable_of_Person_type_name'
@@ -50,8 +52,8 @@ module Ransack
50
52
  it 'accepts arrays of groupings' do
51
53
  search = Search.new(Person,
52
54
  :g => [
53
- {:m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie'},
54
- {:m => 'or', :name_eq => 'Bert', :children_name_eq => 'Bert'},
55
+ { :m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie' },
56
+ { :m => 'or', :name_eq => 'Bert', :children_name_eq => 'Bert' },
55
57
  ]
56
58
  )
57
59
  ors = search.groupings
@@ -66,8 +68,8 @@ module Ransack
66
68
  it 'accepts "attributes" hashes for groupings' do
67
69
  search = Search.new(Person,
68
70
  :g => {
69
- '0' => {:m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie'},
70
- '1' => {:m => 'or', :name_eq => 'Bert', :children_name_eq => 'Bert'},
71
+ '0' => { :m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie' },
72
+ '1' => { :m => 'or', :name_eq => 'Bert', :children_name_eq => 'Bert' },
71
73
  }
72
74
  )
73
75
  ors = search.groupings
@@ -82,8 +84,8 @@ module Ransack
82
84
  it 'accepts "attributes" hashes for conditions' do
83
85
  search = Search.new(Person,
84
86
  :c => {
85
- '0' => {:a => ['name'], :p => 'eq', :v => ['Ernie']},
86
- '1' => {:a => ['children_name', 'parent_name'], :p => 'eq', :v => ['Ernie'], :m => 'or'}
87
+ '0' => { :a => ['name'], :p => 'eq', :v => ['Ernie'] },
88
+ '1' => { :a => ['children_name', 'parent_name'], :p => 'eq', :v => ['Ernie'], :m => 'or' }
87
89
  }
88
90
  )
89
91
  conditions = search.base.conditions
@@ -93,8 +95,7 @@ module Ransack
93
95
 
94
96
  it 'creates Conditions for custom predicates that take arrays' do
95
97
  Ransack.configure do |config|
96
- config.add_predicate 'ary_pred',
97
- :wants_array => true
98
+ config.add_predicate 'ary_pred', :wants_array => true
98
99
  end
99
100
 
100
101
  search = Search.new(Person, :name_ary_pred => ['Ernie', 'Bert'])
@@ -135,11 +136,12 @@ module Ransack
135
136
 
136
137
  it 'evaluates nested conditions' do
137
138
  search = Search.new(Person, :children_name_eq => 'Ernie',
138
- :g => [{
139
- :m => 'or',
140
- :name_eq => 'Ernie',
141
- :children_children_name_eq => 'Ernie'
142
- }]
139
+ :g => [
140
+ { :m => 'or',
141
+ :name_eq => 'Ernie',
142
+ :children_children_name_eq => 'Ernie'
143
+ }
144
+ ]
143
145
  )
144
146
  search.result.should be_an ActiveRecord::Relation
145
147
  where = search.result.where_values.first
@@ -151,8 +153,8 @@ module Ransack
151
153
  it 'evaluates arrays of groupings' do
152
154
  search = Search.new(Person,
153
155
  :g => [
154
- {:m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie'},
155
- {:m => 'or', :name_eq => 'Bert', :children_name_eq => 'Bert'},
156
+ { :m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie' },
157
+ { :m => 'or', :name_eq => 'Bert', :children_name_eq => 'Bert' },
156
158
  ]
157
159
  )
158
160
  search.result.should be_an ActiveRecord::Relation
@@ -166,10 +168,25 @@ module Ransack
166
168
  end
167
169
 
168
170
  it 'returns distinct records when passed :distinct => true' do
169
- search = Search.new(Person, :g => [{:m => 'or', :comments_body_cont => 'e', :articles_comments_body_cont => 'e'}])
170
- search.result.all.should have(920).items
171
- search.result(:distinct => true).should have(330).items
172
- search.result.all.uniq.should eq search.result(:distinct => true).all
171
+ search = Search.new(
172
+ Person, :g => [
173
+ { :m => 'or',
174
+ :comments_body_cont => 'e',
175
+ :articles_comments_body_cont => 'e'
176
+ }
177
+ ]
178
+ )
179
+ if ActiveRecord::VERSION::MAJOR == 3
180
+ all_or_load, uniq_or_distinct = :all, :uniq
181
+ else
182
+ all_or_load, uniq_or_distinct = :load, :distinct
183
+ end
184
+ search.result.send(all_or_load).
185
+ should have(920).items
186
+ search.result(:distinct => true).
187
+ should have(330).items
188
+ search.result.send(all_or_load).send(uniq_or_distinct).
189
+ should eq search.result(:distinct => true).send(all_or_load)
173
190
  end
174
191
  end
175
192
 
@@ -201,22 +218,21 @@ module Ransack
201
218
 
202
219
  it 'creates sorts based on multiple attributes/directions in hash format' do
203
220
  @s.sorts = {
204
- '0' => {
205
- :name => 'id',
206
- :dir => 'desc'
207
- },
208
- '1' => {
209
- :name => 'name',
210
- :dir => 'asc'
211
- }
221
+ '0' => { :name => 'id', :dir => 'desc' },
222
+ '1' => { :name => 'name', :dir => 'asc' }
212
223
  }
213
224
  @s.sorts.should have(2).items
214
- @s.sorts.should be_all {|s| Nodes::Sort === s}
215
- id_sort = @s.sorts.detect {|s| s.name == 'id'}
216
- name_sort = @s.sorts.detect {|s| s.name == 'name'}
225
+ @s.sorts.should be_all { |s| Nodes::Sort === s }
226
+ id_sort = @s.sorts.detect { |s| s.name == 'id' }
227
+ name_sort = @s.sorts.detect { |s| s.name == 'name' }
217
228
  id_sort.dir.should eq 'desc'
218
229
  name_sort.dir.should eq 'asc'
219
230
  end
231
+
232
+ it 'overrides existing sort' do
233
+ @s.sorts = 'id asc'
234
+ @s.result.first.id.should eq 1
235
+ end
220
236
  end
221
237
 
222
238
  describe '#method_missing' do
@@ -225,7 +241,7 @@ module Ransack
225
241
  end
226
242
 
227
243
  it 'raises NoMethodError when sent an invalid attribute' do
228
- expect {@s.blah}.to raise_error NoMethodError
244
+ expect { @s.blah }.to raise_error NoMethodError
229
245
  end
230
246
 
231
247
  it 'sets condition attributes when sent valid attributes' do
@@ -234,8 +250,7 @@ module Ransack
234
250
  end
235
251
 
236
252
  it 'allows chaining to access nested conditions' do
237
- @s.groupings = [{:m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie'}]
238
- @s.groupings.first.name_eq.should eq 'Ernie'
253
+ @s.groupings = [{ :m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie' }]
239
254
  @s.groupings.first.children_name_eq.should eq 'Ernie'
240
255
  end
241
256
  end