ransack 1.7.0 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +40 -22
  3. data/CHANGELOG.md +176 -27
  4. data/CONTRIBUTING.md +30 -19
  5. data/Gemfile +8 -3
  6. data/README.md +131 -58
  7. data/Rakefile +5 -2
  8. data/lib/ransack.rb +10 -5
  9. data/lib/ransack/adapters.rb +43 -23
  10. data/lib/ransack/adapters/active_record.rb +2 -2
  11. data/lib/ransack/adapters/active_record/3.0/compat.rb +5 -5
  12. data/lib/ransack/adapters/active_record/3.0/context.rb +5 -3
  13. data/lib/ransack/adapters/active_record/3.1/context.rb +1 -4
  14. data/lib/ransack/adapters/active_record/base.rb +12 -1
  15. data/lib/ransack/adapters/active_record/context.rb +148 -55
  16. data/lib/ransack/adapters/active_record/ransack/constants.rb +53 -53
  17. data/lib/ransack/adapters/active_record/ransack/context.rb +3 -1
  18. data/lib/ransack/adapters/active_record/ransack/nodes/condition.rb +20 -28
  19. data/lib/ransack/adapters/mongoid/base.rb +21 -6
  20. data/lib/ransack/adapters/mongoid/context.rb +9 -5
  21. data/lib/ransack/configuration.rb +24 -3
  22. data/lib/ransack/constants.rb +11 -22
  23. data/lib/ransack/context.rb +20 -13
  24. data/lib/ransack/helpers/form_builder.rb +5 -6
  25. data/lib/ransack/helpers/form_helper.rb +50 -69
  26. data/lib/ransack/locale/da.yml +70 -0
  27. data/lib/ransack/locale/id.yml +70 -0
  28. data/lib/ransack/locale/ja.yml +70 -0
  29. data/lib/ransack/locale/pt-BR.yml +70 -0
  30. data/lib/ransack/locale/{zh.yml → zh-CN.yml} +1 -1
  31. data/lib/ransack/locale/zh-TW.yml +70 -0
  32. data/lib/ransack/nodes.rb +1 -1
  33. data/lib/ransack/nodes/attribute.rb +4 -1
  34. data/lib/ransack/nodes/bindable.rb +18 -6
  35. data/lib/ransack/nodes/condition.rb +58 -28
  36. data/lib/ransack/nodes/grouping.rb +15 -4
  37. data/lib/ransack/nodes/sort.rb +9 -5
  38. data/lib/ransack/predicate.rb +6 -2
  39. data/lib/ransack/search.rb +6 -5
  40. data/lib/ransack/translate.rb +2 -2
  41. data/lib/ransack/version.rb +1 -1
  42. data/ransack.gemspec +4 -4
  43. data/spec/mongoid/adapters/mongoid/base_spec.rb +20 -1
  44. data/spec/mongoid/nodes/condition_spec.rb +15 -0
  45. data/spec/mongoid/support/mongoid.yml +5 -0
  46. data/spec/mongoid/support/schema.rb +4 -0
  47. data/spec/mongoid_spec_helper.rb +13 -9
  48. data/spec/ransack/adapters/active_record/base_spec.rb +249 -71
  49. data/spec/ransack/adapters/active_record/context_spec.rb +16 -18
  50. data/spec/ransack/helpers/form_builder_spec.rb +5 -2
  51. data/spec/ransack/helpers/form_helper_spec.rb +84 -14
  52. data/spec/ransack/nodes/condition_spec.rb +24 -0
  53. data/spec/ransack/nodes/grouping_spec.rb +56 -0
  54. data/spec/ransack/predicate_spec.rb +5 -5
  55. data/spec/ransack/search_spec.rb +79 -70
  56. data/spec/support/schema.rb +43 -29
  57. metadata +17 -12
@@ -9,11 +9,11 @@ module Ransack
9
9
  describe Context do
10
10
  subject { Context.new(Person) }
11
11
 
12
- if AR_version >= '3.1'
13
- it 'has an Active Record alias tracker method' do
14
- expect(subject.alias_tracker)
15
- .to be_an ::ActiveRecord::Associations::AliasTracker
16
- end
12
+
13
+ it 'has an Active Record alias tracker method',
14
+ if: AR_version >= '3.1' do
15
+ expect(subject.alias_tracker)
16
+ .to be_an ::ActiveRecord::Associations::AliasTracker
17
17
  end
18
18
 
19
19
  describe '#relation_for' do
@@ -24,8 +24,8 @@ module Ransack
24
24
 
25
25
  describe '#evaluate' do
26
26
  it 'evaluates search objects' do
27
- search = Search.new(Person, :name_eq => 'Joe Blow')
28
- result = subject.evaluate(search)
27
+ s = Search.new(Person, name_eq: 'Joe Blow')
28
+ result = subject.evaluate(s)
29
29
 
30
30
  expect(result).to be_an ::ActiveRecord::Relation
31
31
  expect(result.to_sql)
@@ -33,25 +33,25 @@ module Ransack
33
33
  end
34
34
 
35
35
  it 'SELECTs DISTINCT when distinct: true' do
36
- search = Search.new(Person, :name_eq => 'Joe Blow')
37
- result = subject.evaluate(search, :distinct => true)
36
+ s = Search.new(Person, name_eq: 'Joe Blow')
37
+ result = subject.evaluate(s, distinct: true)
38
38
 
39
39
  expect(result).to be_an ::ActiveRecord::Relation
40
40
  expect(result.to_sql).to match /SELECT DISTINCT/
41
41
  end
42
42
  end
43
43
 
44
- describe "sharing context across searches" do
44
+ describe 'sharing context across searches' do
45
45
  let(:shared_context) { Context.for(Person) }
46
46
 
47
47
  before do
48
- Search.new(Person, { :parent_name_eq => 'A' },
48
+ Search.new(Person, { parent_name_eq: 'A' },
49
49
  context: shared_context)
50
- Search.new(Person, { :children_name_eq => 'B' },
50
+ Search.new(Person, { children_name_eq: 'B' },
51
51
  context: shared_context)
52
52
  end
53
53
 
54
- describe '#join_associations', :if => AR_version <= '4.0' do
54
+ describe '#join_associations', if: AR_version <= '4.0' do
55
55
  it 'returns dependent join associations for all searches run
56
56
  against the context' do
57
57
  parents, children = shared_context.join_associations
@@ -69,18 +69,16 @@ module Ransack
69
69
  end
70
70
 
71
71
  describe '#join_sources' do
72
- # FIXME: fix this test for Rails 4.2.
72
+ # FIXME: fix this test for Rails 4.2 and 5.0.
73
73
  it 'returns dependent arel join nodes for all searches run against
74
- the context',
75
- :if => %w(3.1 3.2 4.0 4.1).include?(AR_version) do
74
+ the context', if: %w(3.1 3.2 4.0 4.1).include?(AR_version) do
76
75
  parents, children = shared_context.join_sources
77
-
78
76
  expect(children.left.name).to eq "children_people"
79
77
  expect(parents.left.name).to eq "parents_people"
80
78
  end
81
79
 
82
80
  it 'can be rejoined to execute a valid query',
83
- :if => AR_version >= '3.1' do
81
+ if: AR_version >= '3.1' do
84
82
  parents, children = shared_context.join_sources
85
83
 
86
84
  expect { Person.joins(parents).joins(children).to_a }
@@ -7,7 +7,6 @@ module Ransack
7
7
  router = ActionDispatch::Routing::RouteSet.new
8
8
  router.draw do
9
9
  resources :people, :comments, :notes
10
- get ':controller(/:action(/:id(.:format)))'
11
10
  end
12
11
 
13
12
  include router.url_helpers
@@ -22,7 +21,11 @@ module Ransack
22
21
  @controller.view_context.search_form_for(@s) { |f| @f = f }
23
22
  end
24
23
 
25
- it 'selects previously-entered time values with datetime_select' do
24
+ it 'selects previously-entered time values with datetime_select',
25
+ unless: (
26
+ RUBY_VERSION >= '2.3' &&
27
+ ::ActiveRecord::VERSION::STRING.first(3) < '3.2'
28
+ ) do
26
29
  date_values = %w(2011 1 2 03 04 05)
27
30
  # @s.created_at_eq = date_values # This works in Rails 4.x but not 3.x
28
31
  @s.created_at_eq = [2011, 1, 2, 3, 4, 5] # so we have to do this
@@ -10,7 +10,6 @@ module Ransack
10
10
  namespace :admin do
11
11
  resources :comments
12
12
  end
13
- get ':controller(/:action(/:id(.:format)))'
14
13
  end
15
14
 
16
15
  include router.url_helpers
@@ -19,13 +18,8 @@ module Ransack
19
18
  before do
20
19
  @controller = ActionView::TestCase::TestController.new
21
20
  @controller.instance_variable_set(:@_routes, router)
22
- @controller.class_eval do
23
- include router.url_helpers
24
- end
25
-
26
- @controller.view_context_class.class_eval do
27
- include router.url_helpers
28
- end
21
+ @controller.class_eval { include router.url_helpers }
22
+ @controller.view_context_class.class_eval { include router.url_helpers }
29
23
  end
30
24
 
31
25
  describe '#sort_link with default search_key' do
@@ -316,12 +310,13 @@ module Ransack
316
310
  end
317
311
 
318
312
  context 'view has existing parameters' do
319
- before do
320
- @controller.view_context.params.merge!({ exist: 'existing' })
321
- end
313
+
322
314
  describe '#sort_link should not remove existing params' do
323
- subject { @controller.view_context
324
- .sort_link(
315
+
316
+ before { @controller.view_context.params[:exist] = 'existing' }
317
+
318
+ subject {
319
+ @controller.view_context.sort_link(
325
320
  Person.search(
326
321
  { sorts: ['name desc'] },
327
322
  search_key: 'people_search'
@@ -330,8 +325,44 @@ module Ransack
330
325
  controller: 'people'
331
326
  )
332
327
  }
328
+
333
329
  it { should match /exist\=existing/ }
334
330
  end
331
+
332
+ context 'using a real ActionController::Parameter object',
333
+ if: ::ActiveRecord::VERSION::MAJOR > 3 do
334
+
335
+ describe 'with symbol q:, #sort_link should include search params' do
336
+ subject { @controller.view_context.sort_link(Person.search, :name) }
337
+ let(:params) { ActionController::Parameters.new(
338
+ { :q => { name_eq: 'TEST' }, controller: 'people' }
339
+ ) }
340
+ before { @controller.instance_variable_set(:@params, params) }
341
+
342
+ it {
343
+ should match(
344
+ /people\?q(%5B|\[)name_eq(%5D|\])=TEST&amp;q(%5B|\[)s(%5D|\])
345
+ =name\+asc/x,
346
+ )
347
+ }
348
+ end
349
+
350
+ describe "with string 'q', #sort_link should include search params" do
351
+ subject { @controller.view_context.sort_link(Person.search, :name) }
352
+ let(:params) {
353
+ ActionController::Parameters.new(
354
+ { 'q' => { name_eq: 'Test2' }, controller: 'people' }
355
+ ) }
356
+ before { @controller.instance_variable_set(:@params, params) }
357
+
358
+ it {
359
+ should match(
360
+ /people\?q(%5B|\[)name_eq(%5D|\])=Test2&amp;q(%5B|\[)s(%5D|\])
361
+ =name\+asc/x,
362
+ )
363
+ }
364
+ end
365
+ end
335
366
  end
336
367
 
337
368
  describe '#sort_link with hide order indicator set to true' do
@@ -344,6 +375,7 @@ module Ransack
344
375
  )
345
376
  }
346
377
  it { should match /Full Name/ }
378
+ it { should_not match /&#9660;|&#9650;/ }
347
379
  end
348
380
 
349
381
  describe '#sort_link with hide order indicator set to false' do
@@ -358,6 +390,45 @@ module Ransack
358
390
  it { should match /Full Name&nbsp;&#9660;/ }
359
391
  end
360
392
 
393
+ describe '#sort_link with config set to globally hide order indicators' do
394
+ before do
395
+ Ransack.configure { |c| c.hide_sort_order_indicators = true }
396
+ end
397
+ subject { @controller.view_context
398
+ .sort_link(
399
+ [:main_app, Person.search(sorts: ['name desc'])],
400
+ :name,
401
+ controller: 'people'
402
+ )
403
+ }
404
+ it { should_not match /&#9660;|&#9650;/ }
405
+ end
406
+
407
+ describe '#sort_link with config set to globally show order indicators' do
408
+ before do
409
+ Ransack.configure { |c| c.hide_sort_order_indicators = false }
410
+ end
411
+ subject { @controller.view_context
412
+ .sort_link(
413
+ [:main_app, Person.search(sorts: ['name desc'])],
414
+ :name,
415
+ controller: 'people'
416
+ )
417
+ }
418
+ it { should match /Full Name&nbsp;&#9660;/ }
419
+ end
420
+
421
+ describe '#sort_link with a block' do
422
+ subject { @controller.view_context
423
+ .sort_link(
424
+ [:main_app, Person.search(sorts: ['name desc'])],
425
+ :name,
426
+ controller: 'people'
427
+ ) { 'Block label' }
428
+ }
429
+ it { should match /Block label&nbsp;&#9660;/ }
430
+ end
431
+
361
432
  describe '#search_form_for with default format' do
362
433
  subject { @controller.view_context
363
434
  .search_form_for(Person.search) {} }
@@ -398,7 +469,6 @@ module Ransack
398
469
  }
399
470
  it { should match /example_name_eq/ }
400
471
  end
401
-
402
472
  end
403
473
  end
404
474
  end
@@ -4,6 +4,21 @@ module Ransack
4
4
  module Nodes
5
5
  describe Condition do
6
6
 
7
+ context 'with an alias' do
8
+ subject {
9
+ Condition.extract(
10
+ Context.for(Person), 'term_start', Person.first(2).map(&:name)
11
+ )
12
+ }
13
+
14
+ specify { expect(subject.combinator).to eq 'or' }
15
+ specify { expect(subject.predicate.name).to eq 'start' }
16
+
17
+ it 'converts the alias to the correct attributes' do
18
+ expect(subject.attributes.map(&:name)).to eq(['name', 'email'])
19
+ end
20
+ end
21
+
7
22
  context 'with multiple values and an _any predicate' do
8
23
  subject {
9
24
  Condition.extract(
@@ -14,6 +29,15 @@ module Ransack
14
29
  specify { expect(subject.values.size).to eq(2) }
15
30
  end
16
31
 
32
+ describe '#negative?' do
33
+ let(:context) { Context.for(Person) }
34
+ let(:eq) { Condition.extract(context, 'name_eq', 'A') }
35
+ let(:not_eq) { Condition.extract(context, 'name_not_eq', 'A') }
36
+
37
+ specify { expect(not_eq.negative?).to be true }
38
+ specify { expect(eq.negative?).to be false }
39
+ end
40
+
17
41
  context 'with an invalid predicate' do
18
42
  subject {
19
43
  Condition.extract(
@@ -50,6 +50,62 @@ module Ransack
50
50
  end
51
51
  end
52
52
 
53
+ describe '#conditions=' do
54
+ context 'when conditions are identical' do
55
+ let(:conditions) do
56
+ {
57
+ '0' => {
58
+ 'a' => { '0'=> { 'name' => 'name', 'ransacker_args' => '' } },
59
+ 'p' => 'cont',
60
+ 'v' => { '0' => { 'value' => 'John' } }
61
+ },
62
+ '1' => {
63
+ 'a' => { '0' => { 'name' => 'name', 'ransacker_args' => '' } },
64
+ 'p' => 'cont',
65
+ 'v' => { '0' => { 'value' => 'John' } }
66
+ }
67
+ }
68
+ end
69
+ before { subject.conditions = conditions }
70
+
71
+ it 'expect duplicates to be removed' do
72
+ expect(subject.conditions.count).to eq 1
73
+ end
74
+ end
75
+
76
+ context 'when conditions differ only by ransacker_args' do
77
+ let(:conditions) do
78
+ {
79
+ '0' => {
80
+ 'a' => {
81
+ '0' => {
82
+ 'name' => 'with_arguments',
83
+ 'ransacker_args' => [1,2]
84
+ }
85
+ },
86
+ 'p' => 'eq',
87
+ 'v' => { '0' => { 'value' => '10' } }
88
+ },
89
+ '1' => {
90
+ 'a' => {
91
+ '0' => {
92
+ 'name' => 'with_arguments',
93
+ 'ransacker_args' => [3,4]
94
+ }
95
+ },
96
+ 'p' => 'eq',
97
+ 'v' => { '0' => { 'value' => '10' } }
98
+ }
99
+ }
100
+ end
101
+ before { subject.conditions = conditions }
102
+
103
+ it 'expect them to be parsed as different and not as duplicates' do
104
+ expect(subject.conditions.count).to eq 2
105
+ end
106
+ end
107
+ end
108
+
53
109
  end
54
110
  end
55
111
  end
@@ -16,7 +16,7 @@ module Ransack
16
16
  expect { subject.result }.to_not raise_error
17
17
  end
18
18
 
19
- it "escapes '%', '.' and '\\\\' in value" do
19
+ it "escapes '%', '.', '_' and '\\\\' in value" do
20
20
  subject.send(:"#{method}=", '%._\\')
21
21
  expect(subject.result.to_sql).to match(regexp)
22
22
  end
@@ -124,9 +124,9 @@ module Ransack
124
124
  describe 'cont' do
125
125
  it_has_behavior 'wildcard escaping', :name_cont,
126
126
  (if ActiveRecord::Base.connection.adapter_name == "PostgreSQL"
127
- /"people"."name" ILIKE '%\\%\\._\\\\%'/
127
+ /"people"."name" ILIKE '%\\%\\.\\_\\\\%'/
128
128
  elsif ActiveRecord::Base.connection.adapter_name == "Mysql2"
129
- /`people`.`name` LIKE '%\\\\%\\\\._\\\\\\\\%'/
129
+ /`people`.`name` LIKE '%\\\\%\\\\.\\\\_\\\\\\\\%'/
130
130
  else
131
131
  /"people"."name" LIKE '%%._\\%'/
132
132
  end) do
@@ -143,9 +143,9 @@ module Ransack
143
143
  describe 'not_cont' do
144
144
  it_has_behavior 'wildcard escaping', :name_not_cont,
145
145
  (if ActiveRecord::Base.connection.adapter_name == "PostgreSQL"
146
- /"people"."name" NOT ILIKE '%\\%\\._\\\\%'/
146
+ /"people"."name" NOT ILIKE '%\\%\\.\\_\\\\%'/
147
147
  elsif ActiveRecord::Base.connection.adapter_name == "Mysql2"
148
- /`people`.`name` NOT LIKE '%\\\\%\\\\._\\\\\\\\%'/
148
+ /`people`.`name` NOT LIKE '%\\\\%\\\\.\\\\_\\\\\\\\%'/
149
149
  else
150
150
  /"people"."name" NOT LIKE '%%._\\%'/
151
151
  end) do
@@ -43,16 +43,16 @@ module Ransack
43
43
 
44
44
  it 'accepts a context option' do
45
45
  shared_context = Context.for(Person)
46
- search1 = Search.new(Person, { name_eq: 'A' }, context: shared_context)
47
- search2 = Search.new(Person, { name_eq: 'B' }, context: shared_context)
48
- expect(search1.context).to be search2.context
46
+ s1 = Search.new(Person, { name_eq: 'A' }, context: shared_context)
47
+ s2 = Search.new(Person, { name_eq: 'B' }, context: shared_context)
48
+ expect(s1.context).to be s2.context
49
49
  end
50
50
  end
51
51
 
52
52
  describe '#build' do
53
53
  it 'creates conditions for top-level attributes' do
54
- search = Search.new(Person, name_eq: 'Ernie')
55
- condition = search.base[:name_eq]
54
+ s = Search.new(Person, name_eq: 'Ernie')
55
+ condition = s.base[:name_eq]
56
56
  expect(condition).to be_a Nodes::Condition
57
57
  expect(condition.predicate.name).to eq 'eq'
58
58
  expect(condition.attributes.first.name).to eq 'name'
@@ -60,8 +60,8 @@ module Ransack
60
60
  end
61
61
 
62
62
  it 'creates conditions for association attributes' do
63
- search = Search.new(Person, children_name_eq: 'Ernie')
64
- condition = search.base[:children_name_eq]
63
+ s = Search.new(Person, children_name_eq: 'Ernie')
64
+ condition = s.base[:children_name_eq]
65
65
  expect(condition).to be_a Nodes::Condition
66
66
  expect(condition.predicate.name).to eq 'eq'
67
67
  expect(condition.attributes.first.name).to eq 'children_name'
@@ -69,8 +69,8 @@ module Ransack
69
69
  end
70
70
 
71
71
  it 'creates conditions for polymorphic belongs_to association attributes' do
72
- search = Search.new(Note, notable_of_Person_type_name_eq: 'Ernie')
73
- condition = search.base[:notable_of_Person_type_name_eq]
72
+ s = Search.new(Note, notable_of_Person_type_name_eq: 'Ernie')
73
+ condition = s.base[:notable_of_Person_type_name_eq]
74
74
  expect(condition).to be_a Nodes::Condition
75
75
  expect(condition.predicate.name).to eq 'eq'
76
76
  expect(condition.attributes.first.name)
@@ -80,9 +80,9 @@ module Ransack
80
80
 
81
81
  it 'creates conditions for multiple polymorphic belongs_to association
82
82
  attributes' do
83
- search = Search.new(Note,
83
+ s = Search.new(Note,
84
84
  notable_of_Person_type_name_or_notable_of_Article_type_title_eq: 'Ernie')
85
- condition = search.
85
+ condition = s.
86
86
  base[:notable_of_Person_type_name_or_notable_of_Article_type_title_eq]
87
87
  expect(condition).to be_a Nodes::Condition
88
88
  expect(condition.predicate.name).to eq 'eq'
@@ -93,15 +93,25 @@ module Ransack
93
93
  expect(condition.value).to eq 'Ernie'
94
94
  end
95
95
 
96
+ it 'creates conditions for aliased attributes',
97
+ if: Ransack::SUPPORTS_ATTRIBUTE_ALIAS do
98
+ s = Search.new(Person, full_name_eq: 'Ernie')
99
+ condition = s.base[:full_name_eq]
100
+ expect(condition).to be_a Nodes::Condition
101
+ expect(condition.predicate.name).to eq 'eq'
102
+ expect(condition.attributes.first.name).to eq 'full_name'
103
+ expect(condition.value).to eq 'Ernie'
104
+ end
105
+
96
106
  it 'preserves default scope and conditions for associations' do
97
- search = Search.new(Person, published_articles_title_eq: 'Test')
98
- expect(search.result.to_sql).to include 'default_scope'
99
- expect(search.result.to_sql).to include 'published'
107
+ s = Search.new(Person, published_articles_title_eq: 'Test')
108
+ expect(s.result.to_sql).to include 'default_scope'
109
+ expect(s.result.to_sql).to include 'published'
100
110
  end
101
111
 
102
112
  it 'discards empty conditions' do
103
- search = Search.new(Person, children_name_eq: '')
104
- condition = search.base[:children_name_eq]
113
+ s = Search.new(Person, children_name_eq: '')
114
+ condition = s.base[:children_name_eq]
105
115
  expect(condition).to be_nil
106
116
  end
107
117
 
@@ -111,13 +121,13 @@ module Ransack
111
121
  end
112
122
 
113
123
  it 'accepts arrays of groupings' do
114
- search = Search.new(Person,
124
+ s = Search.new(Person,
115
125
  g: [
116
126
  { m: 'or', name_eq: 'Ernie', children_name_eq: 'Ernie' },
117
127
  { m: 'or', name_eq: 'Bert', children_name_eq: 'Bert' },
118
128
  ]
119
129
  )
120
- ors = search.groupings
130
+ ors = s.groupings
121
131
  expect(ors.size).to eq(2)
122
132
  or1, or2 = ors
123
133
  expect(or1).to be_a Nodes::Grouping
@@ -126,14 +136,14 @@ module Ransack
126
136
  expect(or2.combinator).to eq 'or'
127
137
  end
128
138
 
129
- it 'accepts "attributes" hashes for groupings' do
130
- search = Search.new(Person,
139
+ it 'accepts attributes hashes for groupings' do
140
+ s = Search.new(Person,
131
141
  g: {
132
142
  '0' => { m: 'or', name_eq: 'Ernie', children_name_eq: 'Ernie' },
133
143
  '1' => { m: 'or', name_eq: 'Bert', children_name_eq: 'Bert' },
134
144
  }
135
145
  )
136
- ors = search.groupings
146
+ ors = s.groupings
137
147
  expect(ors.size).to eq(2)
138
148
  or1, or2 = ors
139
149
  expect(or1).to be_a Nodes::Grouping
@@ -142,8 +152,8 @@ module Ransack
142
152
  expect(or2.combinator).to eq 'or'
143
153
  end
144
154
 
145
- it 'accepts "attributes" hashes for conditions' do
146
- search = Search.new(Person,
155
+ it 'accepts attributes hashes for conditions' do
156
+ s = Search.new(Person,
147
157
  c: {
148
158
  '0' => { a: ['name'], p: 'eq', v: ['Ernie'] },
149
159
  '1' => {
@@ -152,7 +162,7 @@ module Ransack
152
162
  }
153
163
  }
154
164
  )
155
- conditions = search.base.conditions
165
+ conditions = s.base.conditions
156
166
  expect(conditions.size).to eq(2)
157
167
  expect(conditions.map { |c| c.class })
158
168
  .to eq [Nodes::Condition, Nodes::Condition]
@@ -163,8 +173,8 @@ module Ransack
163
173
  config.add_predicate 'ary_pred', wants_array: true
164
174
  end
165
175
 
166
- search = Search.new(Person, name_ary_pred: ['Ernie', 'Bert'])
167
- condition = search.base[:name_ary_pred]
176
+ s = Search.new(Person, name_ary_pred: ['Ernie', 'Bert'])
177
+ condition = s.base[:name_ary_pred]
168
178
  expect(condition).to be_a Nodes::Condition
169
179
  expect(condition.predicate.name).to eq 'ary_pred'
170
180
  expect(condition.attributes.first.name).to eq 'name'
@@ -172,8 +182,8 @@ module Ransack
172
182
  end
173
183
 
174
184
  it 'does not evaluate the query on #inspect' do
175
- search = Search.new(Person, children_id_in: [1, 2, 3])
176
- expect(search.inspect).not_to match /ActiveRecord/
185
+ s = Search.new(Person, children_id_in: [1, 2, 3])
186
+ expect(s.inspect).not_to match /ActiveRecord/
177
187
  end
178
188
 
179
189
  context 'with an invalid condition' do
@@ -211,9 +221,9 @@ module Ransack
211
221
  "#{quote_table_name("children_people")}.#{quote_column_name("name")}"
212
222
  }
213
223
  it 'evaluates conditions contextually' do
214
- search = Search.new(Person, children_name_eq: 'Ernie')
215
- expect(search.result).to be_an ActiveRecord::Relation
216
- expect(search.result.to_sql).to match /#{
224
+ s = Search.new(Person, children_name_eq: 'Ernie')
225
+ expect(s.result).to be_an ActiveRecord::Relation
226
+ expect(s.result.to_sql).to match /#{
217
227
  children_people_name_field} = 'Ernie'/
218
228
  end
219
229
 
@@ -221,51 +231,50 @@ module Ransack
221
231
  # commenting out lines 221 and 242 to run the test. Addresses issue #374.
222
232
  # https://github.com/activerecord-hackery/ransack/issues/374
223
233
  #
224
- if ::ActiveRecord::VERSION::STRING.first(3) == '4.0'
225
- it 'evaluates conditions for multiple belongs_to associations to the
226
- same table contextually' do
227
- s = Search.new(Recommendation,
228
- person_name_eq: 'Ernie',
229
- target_person_parent_name_eq: 'Test'
230
- ).result
231
- expect(s).to be_an ActiveRecord::Relation
232
- real_query = remove_quotes_and_backticks(s.to_sql)
233
- expected_query = <<-SQL
234
- SELECT recommendations.* FROM recommendations
235
- LEFT OUTER JOIN people ON people.id = recommendations.person_id
236
- LEFT OUTER JOIN people target_people_recommendations
237
- ON target_people_recommendations.id = recommendations.target_person_id
238
- LEFT OUTER JOIN people parents_people
239
- ON parents_people.id = target_people_recommendations.parent_id
240
- WHERE ((people.name = 'Ernie' AND parents_people.name = 'Test'))
241
- SQL
242
- .squish
243
- expect(real_query).to eq expected_query
244
- end
234
+ it 'evaluates conditions for multiple `belongs_to` associations to the
235
+ same table contextually',
236
+ if: ::ActiveRecord::VERSION::STRING.first(3) == '4.0' do
237
+ s = Search.new(
238
+ Recommendation,
239
+ person_name_eq: 'Ernie',
240
+ target_person_parent_name_eq: 'Test'
241
+ ).result
242
+ expect(s).to be_an ActiveRecord::Relation
243
+ real_query = remove_quotes_and_backticks(s.to_sql)
244
+ expected_query = <<-SQL
245
+ SELECT recommendations.* FROM recommendations
246
+ LEFT OUTER JOIN people ON people.id = recommendations.person_id
247
+ LEFT OUTER JOIN people target_people_recommendations
248
+ ON target_people_recommendations.id = recommendations.target_person_id
249
+ LEFT OUTER JOIN people parents_people
250
+ ON parents_people.id = target_people_recommendations.parent_id
251
+ WHERE ((people.name = 'Ernie' AND parents_people.name = 'Test'))
252
+ SQL
253
+ .squish
254
+ expect(real_query).to eq expected_query
245
255
  end
246
256
 
247
257
  it 'evaluates compound conditions contextually' do
248
- search = Search.new(Person, children_name_or_name_eq: 'Ernie').result
249
- expect(search).to be_an ActiveRecord::Relation
250
- expect(search.to_sql).to match /#{children_people_name_field
258
+ s = Search.new(Person, children_name_or_name_eq: 'Ernie').result
259
+ expect(s).to be_an ActiveRecord::Relation
260
+ expect(s.to_sql).to match /#{children_people_name_field
251
261
  } = 'Ernie' OR #{people_name_field} = 'Ernie'/
252
262
  end
253
263
 
254
264
  it 'evaluates polymorphic belongs_to association conditions contextually' do
255
- search = Search.new(Note, notable_of_Person_type_name_eq: 'Ernie')
256
- .result
257
- expect(search).to be_an ActiveRecord::Relation
258
- expect(search.to_sql).to match /#{people_name_field} = 'Ernie'/
265
+ s = Search.new(Note, notable_of_Person_type_name_eq: 'Ernie').result
266
+ expect(s).to be_an ActiveRecord::Relation
267
+ expect(s.to_sql).to match /#{people_name_field} = 'Ernie'/
259
268
  end
260
269
 
261
270
  it 'evaluates nested conditions' do
262
- search = Search.new(Person, children_name_eq: 'Ernie',
271
+ s = Search.new(Person, children_name_eq: 'Ernie',
263
272
  g: [
264
273
  { m: 'or', name_eq: 'Ernie', children_children_name_eq: 'Ernie' }
265
274
  ]
266
275
  ).result
267
- expect(search).to be_an ActiveRecord::Relation
268
- first, last = search.to_sql.split(/ AND /)
276
+ expect(s).to be_an ActiveRecord::Relation
277
+ first, last = s.to_sql.split(/ AND /)
269
278
  expect(first).to match /#{children_people_name_field} = 'Ernie'/
270
279
  expect(last).to match /#{
271
280
  people_name_field} = 'Ernie' OR #{
@@ -274,14 +283,14 @@ module Ransack
274
283
  end
275
284
 
276
285
  it 'evaluates arrays of groupings' do
277
- search = Search.new(Person,
286
+ s = Search.new(Person,
278
287
  g: [
279
288
  { m: 'or', name_eq: 'Ernie', children_name_eq: 'Ernie' },
280
289
  { m: 'or', name_eq: 'Bert', children_name_eq: 'Bert' }
281
290
  ]
282
291
  ).result
283
- expect(search).to be_an ActiveRecord::Relation
284
- first, last = search.to_sql.split(/ AND /)
292
+ expect(s).to be_an ActiveRecord::Relation
293
+ first, last = s.to_sql.split(/ AND /)
285
294
  expect(first).to match /#{people_name_field} = 'Ernie' OR #{
286
295
  children_people_name_field} = 'Ernie'/
287
296
  expect(last).to match /#{people_name_field} = 'Bert' OR #{
@@ -289,7 +298,7 @@ module Ransack
289
298
  end
290
299
 
291
300
  it 'returns distinct records when passed distinct: true' do
292
- search = Search.new(Person,
301
+ s = Search.new(Person,
293
302
  g: [
294
303
  { m: 'or', comments_body_cont: 'e', articles_comments_body_cont: 'e' }
295
304
  ]
@@ -299,12 +308,12 @@ module Ransack
299
308
  else
300
309
  all_or_load, uniq_or_distinct = :load, :distinct
301
310
  end
302
- expect(search.result.send(all_or_load).size)
311
+ expect(s.result.send(all_or_load).size)
303
312
  .to eq(9000)
304
- expect(search.result(distinct: true).size)
313
+ expect(s.result(distinct: true).size)
305
314
  .to eq(10)
306
- expect(search.result.send(all_or_load).send(uniq_or_distinct))
307
- .to eq search.result(distinct: true).send(all_or_load)
315
+ expect(s.result.send(all_or_load).send(uniq_or_distinct))
316
+ .to eq s.result(distinct: true).send(all_or_load)
308
317
  end
309
318
 
310
319
  private