8000 Add global and per column options to order null values last · jbox-web/ajax-datatables-rails@0d8ad12 · GitHub
[go: up one dir, main page]

Skip to content

Commit 0d8ad12

Browse files
committed
Add global and per column options to order null values last
1 parent af0a2b9 commit 0d8ad12

File tree

9 files changed

+87
-3
lines changed

9 files changed

+87
-3
lines changed

lib/ajax-datatables-rails/config.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,6 @@ class Configuration
2626

2727
config_accessor(:orm) { :active_record }
2828
config_accessor(:db_adapter) { :postgresql }
29+
config_accessor(:nulls_last) { false }
2930
end
3031
end

lib/ajax-datatables-rails/datatable/column/order.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ def sort_query
1818
custom_field? ? source : "#{table.name}.#{sort_field}"
1919
end
2020

21+
# Add option to sort null values last
22+
def nulls_last
23+
@view_column[:nulls_last] || (@options[:nulls_last] == 'true')
24+
end
25+
2126
end
2227
end
2328
end

lib/ajax-datatables-rails/datatable/simple_order.rb

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@ def initialize(datatable, options = {})
1212
end
1313

1414
def query(sort_column)
15-
"#{sort_column} #{direction}"
15+
if sort_nulls_last?
16+
"CASE WHEN #{sort_column} IS NULL THEN 1 ELSE 0 END, #{sort_column} #{direction}"
17+
else
18+
"#{sort_column} #{direction}"
19+
end
1620
end
1721

1822
def column
@@ -33,6 +37,10 @@ def column_direction
3337
@options[:dir].upcase
3438
end
3539

40+
def sort_nulls_last?
41+
column.nulls_last == true || AjaxDatatablesRails.config.nulls_last == true
42+
end
43+
3644
end
3745
end
3846
end

spec/ajax-datatables-rails/datatable/column_spec.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,17 @@
1010
let(:column) { datatable.datatable.columns.first }
1111

1212
before do
13-
datatable.params[:columns] = {'0'=>{'data'=>'username', 'name'=>'', 'searchable'=>'true', 'orderable'=>'true', 'search'=>{'value'=>'searchvalue', 'regex'=>'false'}}}
13+
datatable.params[:columns] = {'0'=>{'data'=>'username', 'name'=>'', 'searchable'=>'true', 'orderable'=>'true', 'search'=>{'value'=>'searchvalue', 'regex'=>'false'}, 'nulls_last'=>'true'}}
1414
end
1515

1616
it 'should be orderable' do
1717
expect(column.orderable?).to eq(true)
1818
end
1919

20+
it 'should sort nulls last' do
21+
expect(column.nulls_last).to eq(true)
22+
end
23+
2024
it 'should be searchable' do
2125
expect(column.searchable?).to eq(true)
2226
end

spec/ajax-datatables-rails/datatable/simple_order_spec.rb

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,39 @@
22

33
describe AjaxDatatablesRails::Datatable::SimpleOrder do
44

5+
let(:view) { double('view', params: sample_params) }
6+
let(:datatable) { ComplexDatatable.new(view).datatable }
57
let(:options) { ActiveSupport::HashWithIndifferentAccess.new({'column' => '1', 'dir' => 'desc'}) }
6-
let(:simple_order) { AjaxDatatablesRails::Datatable::SimpleOrder.new(nil, options) }
8+
let(:simple_order) { AjaxDatatablesRails::Datatable::SimpleOrder.new(datatable, options) }
79

810
describe 'option methods' do
911
it 'sql query' do
1012
expect(simple_order.query('firstname')).to eq('firstname DESC')
1113
end
1214
end
15+
16+
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 }
20+
21+
it 'sql query' do
22+
expect(simple_order.query('email')).to eq(
23+
'CASE WHEN email IS NULL THEN 1 ELSE 0 END, email DESC'
24+
)
25+
end
26+
end
27+
28+
describe 'using column option' do
29+
let(:sorted_datatable) { DatatableOrderNullsLast.new(view).datatable }
30+
let(:nulls_last_order) { AjaxDatatablesRails::Datatable::SimpleOrder.new(sorted_datatable, options) }
31+
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+
)
36+
end
37+
end
38+
end
39+
1340
end

spec/ajax-datatables-rails/orm/active_record_sort_records_spec.rb

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
let(:view) { double('view', params: sample_params) }
66
let(:datatable) { ComplexDatatable.new(view) }
7+
let(:nulls_last_datatable) { DatatableOrderNullsLast.new(view) }
78
let(:records) { User.all }
89

910
before(:each) do
@@ -44,4 +45,33 @@
4445
end
4546
end
4647

48+
describe '#sort_records with nulls last using global config' do
49+
before { AjaxDatatablesRails.config.nulls_last = true }
50+
after { AjaxDatatablesRails.config.nulls_last = false }
51+
52+
it 'can handle multiple sorting columns' do
53+
# set to order by Users username in ascending order, and
54+
# by Users email in descending order
55+
datatable.params[:order]['0'] = { column: '0', dir: 'asc' }
56+
datatable.params[:order]['1'] = { column: '1', dir: 'desc' }
57+
expect(datatable.sort_records(records).to_sql).to include(
58+
'ORDER BY CASE WHEN users.username IS NULL THEN 1 ELSE 0 END, users.username ASC, ' +
59+
'CASE WHEN users.email IS NULL THEN 1 ELSE 0 END, users.email DESC'
60+
)
61+
end
62+
end
63+
64+
describe '#sort_records with nulls last using column config' do
65+
it 'can handle multiple sorting columns' do
66+
# set to order by Users username in ascending order, and
67+
# by Users email in descending order
68+
nulls_last_datatable.params[:order]['0'] = { column: '0', dir: 'asc' }
69+
nulls_last_datatable.params[:order]['1'] = { column: '1', dir: 'desc' }
70+
expect(nulls_last_datatable.sort_records(records).to_sql).to include(
71+
'ORDER BY users.username ASC, ' +
72+
'CASE WHEN users.email IS NULL THEN 1 ELSE 0 END, users.email DESC'
73+
)
74+
end
75+
end
76+
4777
end

spec/spec_helper.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,5 @@
8282
load File.dirname(__FILE__) + '/support/datatable_cond_numeric.rb'
8383
load File.dirname(__FILE__) + '/support/datatable_cond_proc.rb'
8484
load File.dirname(__FILE__) + '/support/datatable_cond_string.rb'
85+
load File.dirname(__FILE__) + '/support/datatable_order_nulls_last.rb'
8586
require File.dirname(__FILE__) + '/support/test_models.rb'
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class DatatableOrderNullsLast < ComplexDatatable
2+
def view_columns
3+
super.deep_merge(email: { nulls_last: true })
4+
end
5+
end

spec/support/test_helpers.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ def get_raw_records
8383
end
8484
end
8585

86+
# class ComplexDatatableHash < ComplexDatatable
87+
# end
88+
8689
class ComplexDatatableArray < ComplexDatatable
8790
def data
8891
records.map do |record|

0 commit comments

Comments
 (0)
0