ransack 1.7.0 → 1.8.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.
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