ajax-datatables-rails 0.4.3 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +120 -0
  3. data/.rubocop.yml +17 -7
  4. data/Appraisals +15 -20
  5. data/CHANGELOG.md +54 -1
  6. data/Gemfile +0 -5
  7. data/Guardfile +16 -0
  8. data/README.md +238 -112
  9. data/Rakefile +1 -0
  10. data/ajax-datatables-rails.gemspec +24 -20
  11. data/bin/_guard-core +29 -0
  12. data/bin/appraisal +29 -0
  13. data/bin/bundle +114 -0
  14. data/bin/guard +29 -0
  15. data/bin/rake +29 -0
  16. data/bin/rspec +29 -0
  17. data/bin/rubocop +29 -0
  18. data/doc/migrate.md +97 -0
  19. data/doc/webpack.md +7 -2
  20. data/gemfiles/{rails_5.2.0.gemfile → rails_5.2.4.gemfile} +3 -5
  21. data/gemfiles/{rails_5.0.7.gemfile → rails_6.0.3.gemfile} +4 -6
  22. data/gemfiles/{rails_5.1.6.gemfile → rails_6.1.0.gemfile} +4 -6
  23. data/lib/ajax-datatables-rails.rb +12 -1
  24. data/lib/ajax-datatables-rails/active_record.rb +7 -0
  25. data/lib/ajax-datatables-rails/base.rb +47 -46
  26. data/lib/ajax-datatables-rails/datatable.rb +6 -0
  27. data/lib/ajax-datatables-rails/datatable/column.rb +65 -20
  28. data/lib/ajax-datatables-rails/datatable/column/date_filter.rb +12 -21
  29. data/lib/ajax-datatables-rails/datatable/column/order.rb +1 -1
  30. data/lib/ajax-datatables-rails/datatable/column/search.rb +37 -22
  31. data/lib/ajax-datatables-rails/datatable/datatable.rb +16 -7
  32. data/lib/ajax-datatables-rails/datatable/simple_order.rb +23 -10
  33. data/lib/ajax-datatables-rails/datatable/simple_search.rb +2 -0
  34. data/lib/ajax-datatables-rails/error.rb +9 -0
  35. data/lib/ajax-datatables-rails/orm.rb +6 -0
  36. data/lib/ajax-datatables-rails/orm/active_record.rb +11 -12
  37. data/lib/ajax-datatables-rails/version.rb +13 -1
  38. data/lib/generators/rails/templates/datatable.rb +1 -1
  39. data/spec/ajax-datatables-rails/base_spec.rb +129 -93
  40. data/spec/ajax-datatables-rails/datatable/column_spec.rb +105 -37
  41. data/spec/ajax-datatables-rails/datatable/datatable_spec.rb +71 -31
  42. data/spec/ajax-datatables-rails/datatable/simple_order_spec.rb +36 -14
  43. data/spec/ajax-datatables-rails/datatable/simple_search_spec.rb +4 -2
  44. data/spec/ajax-datatables-rails/orm/active_record_filter_records_spec.rb +315 -272
  45. data/spec/ajax-datatables-rails/orm/active_record_paginate_records_spec.rb +9 -8
  46. data/spec/ajax-datatables-rails/orm/active_record_sort_records_spec.rb +17 -14
  47. data/spec/factories/user.rb +3 -1
  48. data/spec/install_oracle.sh +9 -3
  49. data/spec/spec_helper.rb +33 -28
  50. data/spec/support/datatables/complex_datatable.rb +31 -0
  51. data/spec/support/datatables/complex_datatable_array.rb +16 -0
  52. data/spec/support/{datatable_cond_date.rb → datatables/datatable_cond_date.rb} +2 -0
  53. data/spec/support/{datatable_cond_numeric.rb → datatables/datatable_cond_numeric.rb} +3 -1
  54. data/spec/support/{datatable_cond_proc.rb → datatables/datatable_cond_proc.rb} +2 -0
  55. data/spec/support/{datatable_cond_string.rb → datatables/datatable_cond_string.rb} +9 -1
  56. data/spec/support/datatables/datatable_cond_unknown.rb +7 -0
  57. data/spec/support/{datatable_order_nulls_last.rb → datatables/datatable_order_nulls_last.rb} +2 -0
  58. data/spec/support/{test_helpers.rb → helpers/params.rb} +17 -42
  59. data/spec/support/{test_models.rb → models/user.rb} +2 -0
  60. data/spec/support/schema.rb +3 -1
  61. metadata +76 -75
  62. data/.travis.yml +0 -80
  63. data/gemfiles/rails_4.0.13.gemfile +0 -14
  64. data/gemfiles/rails_4.1.16.gemfile +0 -14
  65. data/gemfiles/rails_4.2.10.gemfile +0 -14
  66. data/lib/ajax-datatables-rails/config.rb +0 -31
  67. data/lib/ajax_datatables_rails.rb +0 -15
  68. data/lib/generators/datatable/config_generator.rb +0 -19
  69. data/lib/generators/datatable/templates/ajax_datatables_rails_config.rb +0 -12
  70. data/spec/ajax-datatables-rails/configuration_spec.rb +0 -43
  71. data/spec/ajax-datatables-rails/extended_spec.rb +0 -20
  72. data/spec/ajax-datatables-rails/orm/active_record_spec.rb +0 -25
@@ -1,58 +1,58 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
- describe AjaxDatatablesRails::Datatable::Column do
5
+ RSpec.describe AjaxDatatablesRails::Datatable::Column do
4
6
 
5
- let(:view) { double('view', params: sample_params) }
6
- let(:datatable) { ComplexDatatable.new(view) }
7
+ let(:datatable) { ComplexDatatable.new(sample_params) }
7
8
 
8
9
  describe 'username column' do
9
10
 
10
11
  let(:column) { datatable.datatable.columns.first }
11
12
 
12
- before do
13
- datatable.params[:columns] = {'0'=>{'data'=>'username', 'name'=>'', 'searchable'=>'true', 'orderable'=>'true', 'search'=>{'value'=>'searchvalue', 'regex'=>'false'}}}
14
- end
13
+ before { datatable.params[:columns]['0'][:search][:value] = 'searchvalue' }
15
14
 
16
- it 'should be orderable' do
15
+ it 'is orderable' do
17
16
  expect(column.orderable?).to eq(true)
18
17
  end
19
18
 
20
- it 'should sort nulls last' do
19
+ it 'sorts nulls last' do
21
20
  expect(column.nulls_last?).to eq(false)
22
21
  end
23
22
 
24
- it 'should be searchable' do
23
+ it 'is searchable' do
25
24
  expect(column.searchable?).to eq(true)
26
25
  end
27
26
 
28
- it 'should be searched' do
27
+ it 'is searched' do
29
28
  expect(column.searched?).to eq(true)
30
29
  end
31
30
 
32
- it 'should have connected to id column' do
31
+ it 'has connected to id column' do
33
32
  expect(column.data).to eq('username')
34
33
  end
35
34
 
36
35
  describe '#data' do
37
- it 'should return the data from params' do
36
+ it 'returns the data from params' do
38
37
  expect(column.data).to eq 'username'
39
38
  end
40
39
  end
41
40
 
42
41
  describe '#source' do
43
- it 'should return the data source from view_column' do
42
+ it 'returns the data source from view_column' do
44
43
  expect(column.source).to eq 'User.username'
45
44
  end
46
45
  end
47
46
 
48
47
  describe '#table' do
49
48
  context 'with ActiveRecord ORM' do
50
- it 'should return the corresponding AR table' do
49
+ it 'returns the corresponding AR table' do
51
50
  expect(column.table).to eq User.arel_table
52
51
  end
53
52
  end
53
+
54
54
  context 'with other ORM' do
55
- it 'should return the corresponding model' do
55
+ it 'returns the corresponding model' do
56
56
  expect(User).to receive(:respond_to?).with(:arel_table).and_return(false)
57
57
  expect(column.table).to eq User
58
58
  end
@@ -60,19 +60,19 @@ describe AjaxDatatablesRails::Datatable::Column do
60
60
  end
61
61
 
62
62
  describe '#model' do
63
- it 'should return the corresponding AR model' do
63
+ it 'returns the corresponding AR model' do
64
64
  expect(column.model).to eq User
65
65
  end
66
66
  end
67
67
 
68
68
  describe '#field' do
69
- it 'should return the corresponding field in DB' do
69
+ it 'returns the corresponding field in DB' do
70
70
  expect(column.field).to eq :username
71
71
  end
72
72
  end
73
73
 
74
74
  describe '#custom_field?' do
75
- it 'should return false if field is bound to an AR field' do
75
+ it 'returns false if field is bound to an AR field' do
76
76
  expect(column.custom_field?).to be false
77
77
  end
78
78
  end
@@ -82,73 +82,141 @@ describe AjaxDatatablesRails::Datatable::Column do
82
82
  expect(column.search).to be_a(AjaxDatatablesRails::Datatable::SimpleSearch)
83
83
  end
84
84
 
85
- it 'should have search value' do
85
+ it 'has search value' do
86
86
  expect(column.search.value).to eq('searchvalue')
87
87
  end
88
88
 
89
- it 'should not regex' do
89
+ it 'does not regex' do
90
90
  expect(column.search.regexp?).to eq false
91
91
  end
92
92
  end
93
93
 
94
94
  describe '#cond' do
95
- it 'should be :like by default' do
95
+ it 'is :like by default' do
96
96
  expect(column.cond).to eq(:like)
97
97
  end
98
98
  end
99
99
 
100
100
  describe '#source' do
101
- it 'should be :like by default' do
101
+ it 'is :like by default' do
102
102
  expect(column.source).to eq('User.username')
103
103
  end
104
104
  end
105
105
 
106
106
  describe '#search_query' do
107
- it 'should buld search query' do
107
+ it 'bulds search query' do
108
108
  expect(column.search_query.to_sql).to include('%searchvalue%')
109
109
  end
110
110
  end
111
111
 
112
112
  describe '#sort_query' do
113
- it 'should build sort query' do
113
+ it 'builds sort query' do
114
114
  expect(column.sort_query).to eq('users.username')
115
115
  end
116
116
  end
117
117
 
118
118
  describe '#use_regex?' do
119
- it 'should be true by default' do
119
+ it 'is true by default' do
120
120
  expect(column.use_regex?).to be true
121
121
  end
122
122
  end
123
123
 
124
- unless AjaxDatatablesRails.old_rails?
125
- describe '#delimiter' do
126
- it 'should be - by default' do
127
- expect(column.delimiter).to eq('-')
128
- end
124
+ describe '#delimiter' do
125
+ it 'is - by default' do
126
+ expect(column.delimiter).to eq('-')
129
127
  end
130
128
  end
131
129
  end
132
130
 
133
- describe '#formater' do
134
- let(:datatable) { DatatableWithFormater.new(view) }
131
+ describe '#formatter' do
132
+ let(:datatable) { DatatableWithFormater.new(sample_params) }
135
133
  let(:column) { datatable.datatable.columns.find { |c| c.data == 'last_name' } }
136
134
 
137
- it 'should be a proc' do
138
- expect(column.formater).to be_a(Proc)
135
+ it 'is a proc' do
136
+ expect(column.formatter).to be_a(Proc)
139
137
  end
140
138
  end
141
139
 
142
140
  describe '#filter' do
143
- let(:datatable) { DatatableCondProc.new(view) }
141
+ let(:datatable) { DatatableCondProc.new(sample_params) }
144
142
  let(:column) { datatable.datatable.columns.find { |c| c.data == 'username' } }
145
143
 
146
- it 'should be a proc' do
144
+ it 'is a proc' do
147
145
  config = column.instance_variable_get('@view_column')
148
146
  filter = config[:cond]
149
147
  expect(filter).to be_a(Proc)
150
- expect(filter).to receive(:call).with(column, column.formated_value)
148
+ expect(filter).to receive(:call).with(column, column.formatted_value)
151
149
  column.filter
152
150
  end
153
151
  end
152
+
153
+ describe '#type_cast' do
154
+ let(:column) { datatable.datatable.columns.first }
155
+
156
+ it 'returns VARCHAR if :db_adapter is :pg' do
157
+ expect(datatable).to receive(:db_adapter) { :pg }
158
+ expect(column.send(:type_cast)).to eq('VARCHAR')
159
+ end
160
+
161
+ it 'returns VARCHAR if :db_adapter is :postgre' do
162
+ expect(datatable).to receive(:db_adapter) { :postgre }
163
+ expect(column.send(:type_cast)).to eq('VARCHAR')
164
+ end
165
+
166
+ it 'returns VARCHAR if :db_adapter is :postgresql' do
167
+ expect(datatable).to receive(:db_adapter) { :postgresql }
168
+ expect(column.send(:type_cast)).to eq('VARCHAR')
169
+ end
170
+
171
+ it 'returns VARCHAR2(4000) if :db_adapter is :oracle' do
172
+ expect(datatable).to receive(:db_adapter) { :oracle }
173
+ expect(column.send(:type_cast)).to eq('VARCHAR2(4000)')
174
+ end
175
+
176
+ it 'returns VARCHAR2(4000) if :db_adapter is :oracleenhanced' do
177
+ expect(datatable).to receive(:db_adapter) { :oracleenhanced }
178
+ expect(column.send(:type_cast)).to eq('VARCHAR2(4000)')
179
+ end
180
+
181
+ it 'returns CHAR if :db_adapter is :mysql2' do
182
+ expect(datatable).to receive(:db_adapter) { :mysql2 }
183
+ expect(column.send(:type_cast)).to eq('CHAR')
184
+ end
185
+
186
+ it 'returns CHAR if :db_adapter is :mysql' do
187
+ expect(datatable).to receive(:db_adapter) { :mysql }
188
+ expect(column.send(:type_cast)).to eq('CHAR')
189
+ end
190
+
191
+ it 'returns TEXT if :db_adapter is :sqlite' do
192
+ expect(datatable).to receive(:db_adapter) { :sqlite }
193
+ expect(column.send(:type_cast)).to eq('TEXT')
194
+ end
195
+
196
+ it 'returns TEXT if :db_adapter is :sqlite3' do
197
+ expect(datatable).to receive(:db_adapter) { :sqlite3 }
198
+ expect(column.send(:type_cast)).to eq('TEXT')
199
+ end
200
+
201
+ it 'returns VARCHAR(4000) if :db_adapter is :sqlserver' do
202
+ expect(datatable).to receive(:db_adapter) { :sqlserver }
203
+ expect(column.send(:type_cast)).to eq('VARCHAR(4000)')
204
+ end
205
+ end
206
+
207
+ describe 'when empty column' do
208
+ before { datatable.params[:columns]['0'][:data] = '' }
209
+
210
+ it 'raises error' do
211
+ expect { datatable.to_json }.to raise_error(AjaxDatatablesRails::Error::InvalidSearchColumn).with_message('Unknown column. Check that `data` field is filled on JS side with the column name')
212
+ end
213
+ end
214
+
215
+ describe 'when unknown column' do
216
+ before { datatable.params[:columns]['0'][:data] = 'foo' }
217
+
218
+ it 'raises error' do
219
+ expect { datatable.to_json }.to raise_error(AjaxDatatablesRails::Error::InvalidSearchColumn).with_message("Check that column 'foo' exists in view_columns")
220
+ end
221
+ end
154
222
  end
@@ -1,22 +1,25 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
- describe AjaxDatatablesRails::Datatable::Datatable do
5
+ RSpec.describe AjaxDatatablesRails::Datatable::Datatable do
4
6
 
5
- let(:view) { double('view', params: sample_params) }
6
- let(:datatable) { ComplexDatatable.new(view).datatable }
7
- let(:order_option) { {'0'=>{'column'=>'0', 'dir'=>'asc'}, '1'=>{'column'=>'1', 'dir'=>'desc'}} }
7
+ let(:datatable) { ComplexDatatable.new(sample_params).datatable }
8
+ let(:datatable_json) { ComplexDatatable.new(sample_params_json).datatable }
9
+ let(:order_option) { { '0' => { 'column' => '0', 'dir' => 'asc' }, '1' => { 'column' => '1', 'dir' => 'desc' } } }
10
+ let(:order_option_json) { [{ 'column' => '0', 'dir' => 'asc' }, { 'column' => '1', 'dir' => 'desc' }] }
8
11
 
9
- describe 'order methods' do
10
- it 'should be orderable' do
12
+ shared_examples 'order methods' do
13
+ it 'is orderable' do
11
14
  expect(datatable.orderable?).to eq(true)
12
15
  end
13
16
 
14
- it 'should not be orderable' do
17
+ it 'is not orderable' do
15
18
  datatable.options[:order] = nil
16
19
  expect(datatable.orderable?).to eq(false)
17
20
  end
18
21
 
19
- it 'should have 2 orderable columns' do
22
+ it 'has 2 orderable columns' do
20
23
  datatable.options[:order] = order_option
21
24
  expect(datatable.orders.count).to eq(2)
22
25
  end
@@ -36,13 +39,35 @@ describe AjaxDatatablesRails::Datatable::Datatable do
36
39
  end
37
40
  end
38
41
 
42
+ shared_examples 'columns methods' do
43
+ it 'has 4 columns' do
44
+ expect(datatable.columns.count).to eq(6)
45
+ end
46
+
47
+ it 'child class' do
48
+ expect(datatable.columns.first).to be_a(AjaxDatatablesRails::Datatable::Column)
49
+ end
50
+ end
51
+
52
+ describe 'with query params' do
53
+ it_behaves_like 'order methods'
54
+ it_behaves_like 'columns methods'
55
+ end
56
+
57
+ describe 'with json params' do
58
+ let(:order_option) { order_option_json }
59
+ let(:datatable) { datatable_json }
60
+ it_behaves_like 'order methods'
61
+ it_behaves_like 'columns methods'
62
+ end
63
+
39
64
  describe 'search methods' do
40
- it 'should be searchable' do
65
+ it 'is searchable' do
41
66
  datatable.options[:search][:value] = 'atom'
42
67
  expect(datatable.searchable?).to eq(true)
43
68
  end
44
69
 
45
- it 'should not be searchable' do
70
+ it 'is not searchable' do
46
71
  datatable.options[:search][:value] = nil
47
72
  expect(datatable.searchable?).to eq(false)
48
73
  end
@@ -52,36 +77,51 @@ describe AjaxDatatablesRails::Datatable::Datatable do
52
77
  end
53
78
  end
54
79
 
55
- describe 'columns methods' do
56
- it 'should have 4 columns' do
57
- expect(datatable.columns.count).to eq(6)
80
+ describe 'option methods' do
81
+ describe '#paginate?' do
82
+ it {
83
+ expect(datatable.paginate?).to be(true)
84
+ }
58
85
  end
59
86
 
60
- it 'child class' do
61
- expect(datatable.columns.first).to be_a(AjaxDatatablesRails::Datatable::Column)
62
- end
63
- end
87
+ describe '#per_page' do
88
+ context 'when params[:length] is missing' do
89
+ it 'defaults to 10' do
90
+ expect(datatable.per_page).to eq(10)
91
+ end
92
+ end
64
93
 
65
- describe 'option methods' do
66
- before :each do
67
- datatable.options[:start] = '50'
68
- datatable.options[:length] = '15'
69
- end
94
+ context 'when params[:length] is passed' do
95
+ let(:datatable) { ComplexDatatable.new({ length: '20' }).datatable }
70
96
 
71
- it 'paginate?' do
72
- expect(datatable.paginate?).to be(true)
97
+ it 'matches the value on view params[:length]' do
98
+ expect(datatable.per_page).to eq(20)
99
+ end
100
+ end
73
101
  end
74
102
 
75
- it 'offset' do
76
- expect(datatable.offset).to eq(50)
77
- end
103
+ describe '#offset' do
104
+ context 'when params[:start] is missing' do
105
+ it 'defaults to 0' do
106
+ expect(datatable.offset).to eq(0)
107
+ end
108
+ end
109
+
110
+ context 'when params[:start] is passed' do
111
+ let(:datatable) { ComplexDatatable.new({ start: '11' }).datatable }
78
112
 
79
- it 'page' do
80
- expect(datatable.page).to eq(4)
113
+ it 'matches the value on view params[:start]' do
114
+ expect(datatable.offset).to eq(11)
115
+ end
116
+ end
81
117
  end
82
118
 
83
- it 'per_page' do
84
- expect(datatable.per_page).to eq(15)
119
+ describe '#page' do
120
+ let(:datatable) { ComplexDatatable.new({ start: '11' }).datatable }
121
+
122
+ it 'calculates page number from params[:start] and #per_page' do
123
+ expect(datatable.page).to eq(2)
124
+ end
85
125
  end
86
126
  end
87
127
  end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
- describe AjaxDatatablesRails::Datatable::SimpleOrder do
5
+ RSpec.describe AjaxDatatablesRails::Datatable::SimpleOrder do
4
6
 
5
- let(:view) { double('view', params: sample_params) }
6
- let(:datatable) { ComplexDatatable.new(view).datatable }
7
- let(:options) { ActiveSupport::HashWithIndifferentAccess.new({'column' => '1', 'dir' => 'desc'}) }
7
+ let(:parent) { ComplexDatatable.new(sample_params) }
8
+ let(:datatable) { parent.datatable }
9
+ let(:options) { ActiveSupport::HashWithIndifferentAccess.new({ 'column' => '1', 'dir' => 'desc' }) }
8
10
  let(:simple_order) { AjaxDatatablesRails::Datatable::SimpleOrder.new(datatable, options) }
9
11
 
10
12
  describe 'option methods' do
@@ -14,27 +16,47 @@ describe AjaxDatatablesRails::Datatable::SimpleOrder do
14
16
  end
15
17
 
16
18
  describe 'option methods with nulls last' do
17
- describe 'using global option' do
18
- before { AjaxDatatablesRails.config.nulls_last = true }
19
- after { AjaxDatatablesRails.config.nulls_last = false }
19
+ describe 'using class option' do
20
+ before { parent.nulls_last = true }
21
+ after { parent.nulls_last = false }
20
22
 
21
23
  it 'sql query' do
24
+ skip('unsupported database adapter') if ENV['DB_ADAPTER'] == 'oracle_enhanced'
25
+
22
26
  expect(simple_order.query('email')).to eq(
23
- 'CASE WHEN email IS NULL THEN 1 ELSE 0 END, email DESC'
27
+ "email DESC #{nulls_last_sql(parent)}"
24
28
  )
25
29
  end
26
30
  end
27
31
 
28
32
  describe 'using column option' do
29
- let(:sorted_datatable) { DatatableOrderNullsLast.new(view).datatable }
33
+ let(:parent) { DatatableOrderNullsLast.new(sample_params) }
34
+ let(:sorted_datatable) { parent.datatable }
30
35
  let(:nulls_last_order) { AjaxDatatablesRails::Datatable::SimpleOrder.new(sorted_datatable, options) }
31
36
 
32
- it 'sql query' do
33
- expect(nulls_last_order.query('email')).to eq(
34
- 'CASE WHEN email IS NULL THEN 1 ELSE 0 END, email DESC'
35
- )
37
+ context 'with postgres database adapter' do
38
+ before { parent.db_adapter = :pg }
39
+
40
+ it 'sql query' do
41
+ expect(nulls_last_order.query('email')).to eq('email DESC NULLS LAST')
42
+ end
43
+ end
44
+
45
+ context 'with sqlite database adapter' do
46
+ before { parent.db_adapter = :sqlite }
47
+
48
+ it 'sql query' do
49
+ expect(nulls_last_order.query('email')).to eq('email DESC IS NULL')
50
+ end
51
+ end
52
+
53
+ context 'with mysql database adapter' do
54
+ before { parent.db_adapter = :mysql }
55
+
56
+ it 'sql query' do
57
+ expect(nulls_last_order.query('email')).to eq('email DESC IS NULL')
58
+ end
36
59
  end
37
60
  end
38
61
  end
39
-
40
62
  end