ajax-datatables-rails 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +26 -0
  3. data/.gitignore +20 -0
  4. data/.rspec +1 -0
  5. data/.rubocop.yml +1157 -0
  6. data/.travis.yml +68 -0
  7. data/Appraisals +34 -0
  8. data/Gemfile +5 -1
  9. data/LICENSE +17 -18
  10. data/README.md +239 -239
  11. data/Rakefile +1 -1
  12. data/ajax-datatables-rails.gemspec +31 -24
  13. data/gemfiles/rails_4.0.13.gemfile +14 -0
  14. data/gemfiles/rails_4.1.15.gemfile +14 -0
  15. data/gemfiles/rails_4.2.8.gemfile +13 -0
  16. data/gemfiles/rails_5.0.3.gemfile +13 -0
  17. data/gemfiles/rails_5.1.1.gemfile +13 -0
  18. data/lib/ajax-datatables-rails.rb +9 -8
  19. data/lib/ajax-datatables-rails/base.rb +80 -156
  20. data/lib/ajax-datatables-rails/config.rb +8 -5
  21. data/lib/ajax-datatables-rails/datatable/column.rb +169 -0
  22. data/lib/ajax-datatables-rails/datatable/column_date_filter.rb +41 -0
  23. data/lib/ajax-datatables-rails/datatable/datatable.rb +79 -0
  24. data/lib/ajax-datatables-rails/datatable/simple_order.rb +31 -0
  25. data/lib/ajax-datatables-rails/datatable/simple_search.rb +18 -0
  26. data/lib/ajax-datatables-rails/orm/active_record.rb +52 -0
  27. data/lib/ajax-datatables-rails/version.rb +1 -1
  28. data/lib/generators/datatable/templates/ajax_datatables_rails_config.rb +3 -3
  29. data/lib/generators/rails/datatable_generator.rb +7 -19
  30. data/lib/generators/rails/templates/datatable.rb +26 -14
  31. data/spec/ajax-datatables-rails/base_spec.rb +190 -0
  32. data/spec/ajax-datatables-rails/configuration_spec.rb +43 -0
  33. data/spec/ajax-datatables-rails/datatable/column_spec.rb +109 -0
  34. data/spec/ajax-datatables-rails/datatable/datatable_spec.rb +87 -0
  35. data/spec/ajax-datatables-rails/datatable/simple_order_spec.rb +13 -0
  36. data/spec/ajax-datatables-rails/datatable/simple_search_spec.rb +17 -0
  37. data/spec/ajax-datatables-rails/extended_spec.rb +20 -0
  38. data/spec/ajax-datatables-rails/orm/active_record_filter_records_spec.rb +439 -0
  39. data/spec/ajax-datatables-rails/orm/active_record_paginate_records_spec.rb +66 -0
  40. data/spec/ajax-datatables-rails/orm/active_record_sort_records_spec.rb +34 -0
  41. data/spec/ajax-datatables-rails/orm/active_record_spec.rb +25 -0
  42. data/spec/factories/user.rb +9 -0
  43. data/spec/install_oracle.sh +12 -0
  44. data/spec/spec_helper.rb +75 -3
  45. data/spec/support/schema.rb +14 -0
  46. data/spec/support/test_helpers.rb +174 -0
  47. data/spec/support/test_models.rb +2 -0
  48. metadata +169 -37
  49. data/lib/ajax-datatables-rails/extensions/kaminari.rb +0 -12
  50. data/lib/ajax-datatables-rails/extensions/simple_paginator.rb +0 -12
  51. data/lib/ajax-datatables-rails/extensions/will_paginate.rb +0 -12
  52. data/lib/ajax-datatables-rails/models.rb +0 -6
  53. data/spec/ajax-datatables-rails/ajax_datatables_rails_spec.rb +0 -351
  54. data/spec/ajax-datatables-rails/kaminari_spec.rb +0 -35
  55. data/spec/ajax-datatables-rails/models_spec.rb +0 -10
  56. data/spec/ajax-datatables-rails/simple_paginator_spec.rb +0 -32
  57. data/spec/ajax-datatables-rails/will_paginate_spec.rb +0 -28
  58. data/spec/schema.rb +0 -35
  59. data/spec/test_models.rb +0 -21
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe AjaxDatatablesRails::Datatable::SimpleOrder do
4
+
5
+ let(:options) { ActiveSupport::HashWithIndifferentAccess.new({'column'=>'1', 'dir'=>'desc'}) }
6
+ let(:simple_order) { AjaxDatatablesRails::Datatable::SimpleOrder.new(nil, options) }
7
+
8
+ describe 'option methods' do
9
+ it 'sql query' do
10
+ expect(simple_order.query('firstname')).to eq('firstname DESC')
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe AjaxDatatablesRails::Datatable::SimpleSearch do
4
+
5
+ let(:options) { ActiveSupport::HashWithIndifferentAccess.new({'value'=>'search value', 'regex'=>'true'}) }
6
+ let(:simple_search) { AjaxDatatablesRails::Datatable::SimpleSearch.new(options) }
7
+
8
+ describe 'option methods' do
9
+ it 'regexp?' do
10
+ expect(simple_search.regexp?).to be(true)
11
+ end
12
+
13
+ it 'value' do
14
+ expect(simple_search.value).to eq('search value')
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe AjaxDatatablesRails::Base do
4
+ let(:view) { double('view', params: sample_params) }
5
+ let(:datatable) { ReallyComplexDatatable.new(view) }
6
+
7
+ describe 'it can transform search value before asking the database' do
8
+ before(:each) do
9
+ create(:user, username: 'johndoe', email: 'johndoe@example.com', last_name: 'DOE')
10
+ create(:user, username: 'msmith', email: 'mary.smith@example.com', last_name: 'SMITH')
11
+ datatable.params[:columns]['3'][:search][:value] = 'doe'
12
+ end
13
+
14
+ it 'should filter records' do
15
+ expect(datatable.data.size).to eq 1
16
+ item = datatable.data.first
17
+ expect(item[:last_name]).to eq 'DOE'
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,439 @@
1
+ require 'spec_helper'
2
+
3
+ describe AjaxDatatablesRails::ORM::ActiveRecord do
4
+
5
+ let(:view) { double('view', params: sample_params) }
6
+ let(:datatable) { ComplexDatatable.new(view) }
7
+ let(:records) { User.all }
8
+
9
+ describe '#filter_records' do
10
+ it 'requires a records collection as argument' do
11
+ expect { datatable.send(:filter_records) }.to raise_error(ArgumentError)
12
+ end
13
+
14
+ it 'performs a simple search first' do
15
+ datatable.params[:search] = { value: 'msmith' }
16
+ expect(datatable).to receive(:build_conditions_for_datatable)
17
+ datatable.send(:filter_records, records)
18
+ end
19
+
20
+ it 'performs a composite search second' do
21
+ datatable.params[:search] = { value: '' }
22
+ expect(datatable).to receive(:build_conditions_for_selected_columns)
23
+ datatable.send(:filter_records, records)
24
+ end
25
+ end
26
+
27
+ describe '#build_conditions_for_datatable' do
28
+ before(:each) do
29
+ create(:user, username: 'johndoe', email: 'johndoe@example.com')
30
+ create(:user, username: 'msmith', email: 'mary.smith@example.com')
31
+ end
32
+
33
+ it 'returns an Arel object' do
34
+ datatable.params[:search] = { value: 'msmith' }
35
+ result = datatable.send(:build_conditions_for_datatable)
36
+ expect(result).to be_a(Arel::Nodes::Grouping)
37
+ end
38
+
39
+ context 'no search query' do
40
+ it 'returns empty query' do
41
+ datatable.params[:search] = { value: '' }
42
+ expect(datatable.send(:build_conditions_for_datatable)).to be_blank
43
+ end
44
+ end
45
+
46
+ context 'none of columns are connected' do
47
+ before(:each) do
48
+ allow(datatable).to receive(:searchable_columns) { [] }
49
+ end
50
+
51
+ it 'returns empty query result' do
52
+ datatable.params[:search] = { value: 'msmith' }
53
+ expect(datatable.send(:build_conditions_for_datatable)).to be_blank
54
+ end
55
+ end
56
+
57
+ context 'with search query' do
58
+ before(:each) do
59
+ datatable.params[:search] = { value: "john", regex: "false" }
60
+ end
61
+
62
+ it 'returns a filtering query' do
63
+ query = datatable.send(:build_conditions_for_datatable)
64
+ results = records.where(query).map(&:username)
65
+ expect(results).to include('johndoe')
66
+ expect(results).not_to include('msmith')
67
+ end
68
+ end
69
+ end
70
+
71
+ describe '#build_conditions_for_selected_columns' do
72
+ before(:each) do
73
+ create(:user, username: 'johndoe', email: 'johndoe@example.com')
74
+ create(:user, username: 'msmith', email: 'mary.smith@example.com')
75
+ end
76
+
77
+ context 'columns include search query' do
78
+ before do
79
+ datatable.params[:columns]['0'][:search][:value] = 'doe'
80
+ datatable.params[:columns]['1'][:search][:value] = 'example'
81
+ end
82
+
83
+ it 'returns an Arel object' do
84
+ result = datatable.send(:build_conditions_for_selected_columns)
85
+ expect(result).to be_a(Arel::Nodes::And)
86
+ end
87
+
88
+ if AjaxDatatablesRails.config.db_adapter == :postgresql
89
+ context 'when db_adapter is postgresql' do
90
+ it 'can call #to_sql on returned object' do
91
+ result = datatable.send(:build_conditions_for_selected_columns)
92
+ expect(result).to respond_to(:to_sql)
93
+ expect(result.to_sql).to eq(
94
+ "CAST(\"users\".\"username\" AS VARCHAR) ILIKE '%doe%' AND CAST(\"users\".\"email\" AS VARCHAR) ILIKE '%example%'"
95
+ )
96
+ end
97
+ end
98
+ end
99
+
100
+ if AjaxDatatablesRails.config.db_adapter.in? %i[oracle oracleenhanced]
101
+ context 'when db_adapter is oracle' do
102
+ it 'can call #to_sql on returned object' do
103
+ result = datatable.send(:build_conditions_for_selected_columns)
104
+ expect(result).to respond_to(:to_sql)
105
+ expect(result.to_sql).to eq(
106
+ "CAST(\"USERS\".\"USERNAME\" AS VARCHAR2(4000)) LIKE '%doe%' AND CAST(\"USERS\".\"EMAIL\" AS VARCHAR2(4000)) LIKE '%example%'"
107
+ )
108
+ end
109
+ end
110
+ end
111
+
112
+ if AjaxDatatablesRails.config.db_adapter.in? %i[mysql2 sqlite3]
113
+ context 'when db_adapter is mysql2' do
114
+ it 'can call #to_sql on returned object' do
115
+ result = datatable.send(:build_conditions_for_selected_columns)
116
+ expect(result).to respond_to(:to_sql)
117
+ expect(result.to_sql).to eq(
118
+ "CAST(`users`.`username` AS CHAR) LIKE '%doe%' AND CAST(`users`.`email` AS CHAR) LIKE '%example%'"
119
+ )
120
+ end
121
+ end
122
+ end
123
+ end
124
+
125
+ it 'calls #build_conditions_for_selected_columns' do
126
+ expect(datatable).to receive(:build_conditions_for_selected_columns)
127
+ datatable.send(:build_conditions)
128
+ end
129
+
130
+ context 'with search values in columns' do
131
+ before(:each) do
132
+ datatable.params[:columns]['0'][:search][:value] = 'doe'
133
+ end
134
+
135
+ it 'returns a filtered set of records' do
136
+ query = datatable.send(:build_conditions_for_selected_columns)
137
+ results = records.where(query).map(&:username)
138
+ expect(results).to include('johndoe')
139
+ expect(results).not_to include('msmith')
140
+ end
141
+ end
142
+ end
143
+
144
+ describe '#typecast helper method' do
145
+ let(:view) { double('view', params: sample_params) }
146
+ let(:column) { ComplexDatatable.new(view).datatable.columns.first }
147
+
148
+ it 'returns VARCHAR if :db_adapter is :pg' do
149
+ allow_any_instance_of(AjaxDatatablesRails::Configuration).to receive(:db_adapter) { :pg }
150
+ expect(column.send(:typecast)).to eq('VARCHAR')
151
+ end
152
+
153
+ it 'returns VARCHAR if :db_adapter is :postgre' do
154
+ allow_any_instance_of(AjaxDatatablesRails::Configuration).to receive(:db_adapter) { :postgre }
155
+ expect(column.send(:typecast)).to eq('VARCHAR')
156
+ end
157
+
158
+ it 'returns VARCHAR if :db_adapter is :postgresql' do
159
+ allow_any_instance_of(AjaxDatatablesRails::Configuration).to receive(:db_adapter) { :postgresql }
160
+ expect(column.send(:typecast)).to eq('VARCHAR')
161
+ end
162
+
163
+ it 'returns VARCHAR if :db_adapter is :oracle' do
164
+ allow_any_instance_of(AjaxDatatablesRails::Configuration).to receive(:db_adapter) { :oracle }
165
+ expect(column.send(:typecast)).to eq('VARCHAR2(4000)')
166
+ end
167
+
168
+ it 'returns VARCHAR if :db_adapter is :oracleenhanced' do
169
+ allow_any_instance_of(AjaxDatatablesRails::Configuration).to receive(:db_adapter) { :oracleenhanced }
170
+ expect(column.send(:typecast)).to eq('VARCHAR2(4000)')
171
+ end
172
+
173
+ it 'returns CHAR if :db_adapter is :mysql2' do
174
+ allow_any_instance_of(AjaxDatatablesRails::Configuration).to receive(:db_adapter) { :mysql2 }
175
+ expect(column.send(:typecast)).to eq('CHAR')
176
+ end
177
+
178
+ it 'returns CHAR if :db_adapter is :mysql' do
179
+ allow_any_instance_of(AjaxDatatablesRails::Configuration).to receive(:db_adapter) { :mysql }
180
+ expect(column.send(:typecast)).to eq('CHAR')
181
+ end
182
+
183
+ it 'returns TEXT if :db_adapter is :sqlite' do
184
+ allow_any_instance_of(AjaxDatatablesRails::Configuration).to receive(:db_adapter) { :sqlite }
185
+ expect(column.send(:typecast)).to eq('TEXT')
186
+ end
187
+
188
+ it 'returns TEXT if :db_adapter is :sqlite3' do
189
+ allow_any_instance_of(AjaxDatatablesRails::Configuration).to receive(:db_adapter) { :sqlite3 }
190
+ expect(column.send(:typecast)).to eq('TEXT')
191
+ end
192
+ end
193
+
194
+ describe 'filter conditions' do
195
+ let(:datatable) { ReallyComplexDatatable.new(view) }
196
+
197
+ unless AjaxDatatablesRails.old_rails?
198
+ describe 'it can filter records with condition :date_range' do
199
+ before(:each) do
200
+ create(:user, username: 'johndoe', email: 'johndoe@example.com', last_name: 'Doe', created_at: '01/01/2000')
201
+ create(:user, username: 'msmith', email: 'mary.smith@example.com', last_name: 'Smith', created_at: '01/02/2000')
202
+ end
203
+
204
+ context 'when range is empty' do
205
+ it 'should not filter records' do
206
+ datatable.params[:columns]['5'][:search][:value] = '-'
207
+ expect(datatable.data.size).to eq 2
208
+ item = datatable.data.first
209
+ expect(item[:last_name]).to eq 'Doe'
210
+ end
211
+ end
212
+
213
+ context 'when start date is filled' do
214
+ it 'should filter records created after this date' do
215
+ datatable.params[:columns]['5'][:search][:value] = '31/12/1999-'
216
+ expect(datatable.data.size).to eq 2
217
+ end
218
+ end
219
+
220
+ context 'when end date is filled' do
221
+ it 'should filter records created before this date' do
222
+ datatable.params[:columns]['5'][:search][:value] = '-31/12/1999'
223
+ expect(datatable.data.size).to eq 0
224
+ end
225
+ end
226
+
227
+ context 'when both date are filled' do
228
+ it 'should filter records created between the range' do
229
+ datatable.params[:columns]['5'][:search][:value] = '01/12/1999-15/01/2000'
230
+ expect(datatable.data.size).to eq 1
231
+ end
232
+ end
233
+
234
+ context 'when another filter is active' do
235
+ context 'when range is empty' do
236
+ it 'should filter records' do
237
+ datatable.params[:columns]['0'][:search][:value] = 'doe'
238
+ datatable.params[:columns]['5'][:search][:value] = '-'
239
+ expect(datatable.data.size).to eq 1
240
+ item = datatable.data.first
241
+ expect(item[:last_name]).to eq 'Doe'
242
+ end
243
+ end
244
+
245
+ context 'when start date is filled' do
246
+ it 'should filter records' do
247
+ datatable.params[:columns]['0'][:search][:value] = 'doe'
248
+ datatable.params[:columns]['5'][:search][:value] = '01/12/1999-'
249
+ expect(datatable.data.size).to eq 1
250
+ item = datatable.data.first
251
+ expect(item[:last_name]).to eq 'Doe'
252
+ end
253
+ end
254
+
255
+ context 'when end date is filled' do
256
+ it 'should filter records' do
257
+ datatable.params[:columns]['0'][:search][:value] = 'doe'
258
+ datatable.params[:columns]['5'][:search][:value] = '-15/01/2000'
259
+ expect(datatable.data.size).to eq 1
260
+ item = datatable.data.first
261
+ expect(item[:last_name]).to eq 'Doe'
262
+ end
263
+ end
264
+
265
+ context 'when both date are filled' do
266
+ it 'should filter records' do
267
+ datatable.params[:columns]['0'][:search][:value] = 'doe'
268
+ datatable.params[:columns]['5'][:search][:value] = '01/12/1999-15/01/2000'
269
+ expect(datatable.data.size).to eq 1
270
+ item = datatable.data.first
271
+ expect(item[:last_name]).to eq 'Doe'
272
+ end
273
+ end
274
+ end
275
+ end
276
+ end
277
+
278
+ describe 'it can filter records with condition :start_with' do
279
+ before(:each) do
280
+ create(:user, first_name: 'John')
281
+ create(:user, first_name: 'Mary')
282
+ end
283
+
284
+ it 'should filter records matching' do
285
+ datatable.params[:columns]['2'][:search][:value] = 'Jo'
286
+ expect(datatable.data.size).to eq 1
287
+ item = datatable.data.first
288
+ expect(item[:first_name]).to eq 'John'
289
+ end
290
+ end
291
+
292
+ describe 'it can filter records with condition :end_with' do
293
+ before(:each) do
294
+ create(:user, last_name: 'JOHN')
295
+ create(:user, last_name: 'MARY')
296
+ end
297
+
298
+ it 'should filter records matching' do
299
+ datatable.params[:columns]['3'][:search][:value] = 'ry'
300
+ expect(datatable.data.size).to eq 1
301
+ item = datatable.data.first
302
+ expect(item[:last_name]).to eq 'MARY'
303
+ end
304
+ end
305
+
306
+ describe 'it can filter records with condition :null_value' do
307
+ before(:each) do
308
+ create(:user, first_name: 'john', email: 'foo@bar.com')
309
+ create(:user, first_name: 'mary', email: nil)
310
+ end
311
+
312
+ context 'when condition is NULL' do
313
+ it 'should filter records matching' do
314
+ datatable.params[:columns]['1'][:search][:value] = 'NULL'
315
+ expect(datatable.data.size).to eq 1
316
+ item = datatable.data.first
317
+ expect(item[:first_name]).to eq 'mary'
318
+ end
319
+ end
320
+
321
+ context 'when condition is !NULL' do
322
+ it 'should filter records matching' do
323
+ datatable.params[:columns]['1'][:search][:value] = '!NULL'
324
+ expect(datatable.data.size).to eq 1
325
+ item = datatable.data.first
326
+ expect(item[:first_name]).to eq 'john'
327
+ end
328
+ end
329
+ end
330
+
331
+ describe 'it can filter records with condition :eq' do
332
+ let(:datatable) { ReallyComplexDatatableEq.new(view) }
333
+
334
+ before(:each) do
335
+ create(:user, first_name: 'john', post_id: 1)
336
+ create(:user, first_name: 'mary', post_id: 2)
337
+ end
338
+
339
+ it 'should filter records matching' do
340
+ datatable.params[:columns]['4'][:search][:value] = 1
341
+ expect(datatable.data.size).to eq 1
342
+ item = datatable.data.first
343
+ expect(item[:first_name]).to eq 'john'
344
+ end
345
+ end
346
+
347
+ describe 'it can filter records with condition :not_eq' do
348
+ let(:datatable) { ReallyComplexDatatableNotEq.new(view) }
349
+
350
+ before(:each) do
351
+ create(:user, first_name: 'john', post_id: 1)
352
+ create(:user, first_name: 'mary', post_id: 2)
353
+ end
354
+
355
+ it 'should filter records matching' do
356
+ datatable.params[:columns]['4'][:search][:value] = 1
357
+ expect(datatable.data.size).to eq 1
358
+ item = datatable.data.first
359
+ expect(item[:first_name]).to eq 'mary'
360
+ end
361
+ end
362
+
363
+ describe 'it can filter records with condition :lt' do
364
+ let(:datatable) { ReallyComplexDatatableLt.new(view) }
365
+
366
+ before(:each) do
367
+ create(:user, first_name: 'john', post_id: 1)
368
+ create(:user, first_name: 'mary', post_id: 2)
369
+ end
370
+
371
+ it 'should filter records matching' do
372
+ datatable.params[:columns]['4'][:search][:value] = 2
373
+ expect(datatable.data.size).to eq 1
374
+ item = datatable.data.first
375
+ expect(item[:first_name]).to eq 'john'
376
+ end
377
+ end
378
+
379
+ describe 'it can filter records with condition :gt' do
380
+ let(:datatable) { ReallyComplexDatatableGt.new(view) }
381
+
382
+ before(:each) do
383
+ create(:user, first_name: 'john', post_id: 1)
384
+ create(:user, first_name: 'mary', post_id: 2)
385
+ end
386
+
387
+ it 'should filter records matching' do
388
+ datatable.params[:columns]['4'][:search][:value] = 1
389
+ expect(datatable.data.size).to eq 1
390
+ item = datatable.data.first
391
+ expect(item[:first_name]).to eq 'mary'
392
+ end
393
+ end
394
+
395
+ describe 'it can filter records with condition :lteq' do
396
+ let(:datatable) { ReallyComplexDatatableLteq.new(view) }
397
+
398
+ before(:each) do
399
+ create(:user, first_name: 'john', post_id: 1)
400
+ create(:user, first_name: 'mary', post_id: 2)
401
+ end
402
+
403
+ it 'should filter records matching' do
404
+ datatable.params[:columns]['4'][:search][:value] = 2
405
+ expect(datatable.data.size).to eq 2
406
+ end
407
+ end
408
+
409
+ describe 'it can filter records with condition :gteq' do
410
+ let(:datatable) { ReallyComplexDatatableGteq.new(view) }
411
+
412
+ before(:each) do
413
+ create(:user, first_name: 'john', post_id: 1)
414
+ create(:user, first_name: 'mary', post_id: 2)
415
+ end
416
+
417
+ it 'should filter records matching' do
418
+ datatable.params[:columns]['4'][:search][:value] = 1
419
+ expect(datatable.data.size).to eq 2
420
+ end
421
+ end
422
+
423
+ describe 'it can filter records with condition :in' do
424
+ let(:datatable) { ReallyComplexDatatableIn.new(view) }
425
+
426
+ before(:each) do
427
+ create(:user, first_name: 'john', post_id: 1)
428
+ create(:user, first_name: 'mary', post_id: 2)
429
+ end
430
+
431
+ it 'should filter records matching' do
432
+ datatable.params[:columns]['4'][:search][:value] = [1]
433
+ expect(datatable.data.size).to eq 1
434
+ item = datatable.data.first
435
+ expect(item[:first_name]).to eq 'john'
436
+ end
437
+ end
438
+ end
439
+ end