ajax-datatables-rails 0.4.3 → 1.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +120 -0
- data/.rubocop.yml +17 -7
- data/Appraisals +15 -20
- data/CHANGELOG.md +54 -1
- data/Gemfile +0 -5
- data/Guardfile +16 -0
- data/README.md +238 -112
- data/Rakefile +1 -0
- data/ajax-datatables-rails.gemspec +24 -20
- data/bin/_guard-core +29 -0
- data/bin/appraisal +29 -0
- data/bin/bundle +114 -0
- data/bin/guard +29 -0
- data/bin/rake +29 -0
- data/bin/rspec +29 -0
- data/bin/rubocop +29 -0
- data/doc/migrate.md +97 -0
- data/doc/webpack.md +7 -2
- data/gemfiles/{rails_5.2.0.gemfile → rails_5.2.4.gemfile} +3 -5
- data/gemfiles/{rails_5.0.7.gemfile → rails_6.0.3.gemfile} +4 -6
- data/gemfiles/{rails_5.1.6.gemfile → rails_6.1.0.gemfile} +4 -6
- data/lib/ajax-datatables-rails.rb +12 -1
- data/lib/ajax-datatables-rails/active_record.rb +7 -0
- data/lib/ajax-datatables-rails/base.rb +47 -46
- data/lib/ajax-datatables-rails/datatable.rb +6 -0
- data/lib/ajax-datatables-rails/datatable/column.rb +65 -20
- data/lib/ajax-datatables-rails/datatable/column/date_filter.rb +12 -21
- data/lib/ajax-datatables-rails/datatable/column/order.rb +1 -1
- data/lib/ajax-datatables-rails/datatable/column/search.rb +37 -22
- data/lib/ajax-datatables-rails/datatable/datatable.rb +16 -7
- data/lib/ajax-datatables-rails/datatable/simple_order.rb +23 -10
- data/lib/ajax-datatables-rails/datatable/simple_search.rb +2 -0
- data/lib/ajax-datatables-rails/error.rb +9 -0
- data/lib/ajax-datatables-rails/orm.rb +6 -0
- data/lib/ajax-datatables-rails/orm/active_record.rb +11 -12
- data/lib/ajax-datatables-rails/version.rb +13 -1
- data/lib/generators/rails/templates/datatable.rb +1 -1
- data/spec/ajax-datatables-rails/base_spec.rb +129 -93
- data/spec/ajax-datatables-rails/datatable/column_spec.rb +105 -37
- data/spec/ajax-datatables-rails/datatable/datatable_spec.rb +71 -31
- data/spec/ajax-datatables-rails/datatable/simple_order_spec.rb +36 -14
- data/spec/ajax-datatables-rails/datatable/simple_search_spec.rb +4 -2
- data/spec/ajax-datatables-rails/orm/active_record_filter_records_spec.rb +315 -272
- data/spec/ajax-datatables-rails/orm/active_record_paginate_records_spec.rb +9 -8
- data/spec/ajax-datatables-rails/orm/active_record_sort_records_spec.rb +17 -14
- data/spec/factories/user.rb +3 -1
- data/spec/install_oracle.sh +9 -3
- data/spec/spec_helper.rb +33 -28
- data/spec/support/datatables/complex_datatable.rb +31 -0
- data/spec/support/datatables/complex_datatable_array.rb +16 -0
- data/spec/support/{datatable_cond_date.rb → datatables/datatable_cond_date.rb} +2 -0
- data/spec/support/{datatable_cond_numeric.rb → datatables/datatable_cond_numeric.rb} +3 -1
- data/spec/support/{datatable_cond_proc.rb → datatables/datatable_cond_proc.rb} +2 -0
- data/spec/support/{datatable_cond_string.rb → datatables/datatable_cond_string.rb} +9 -1
- data/spec/support/datatables/datatable_cond_unknown.rb +7 -0
- data/spec/support/{datatable_order_nulls_last.rb → datatables/datatable_order_nulls_last.rb} +2 -0
- data/spec/support/{test_helpers.rb → helpers/params.rb} +17 -42
- data/spec/support/{test_models.rb → models/user.rb} +2 -0
- data/spec/support/schema.rb +3 -1
- metadata +76 -75
- data/.travis.yml +0 -80
- data/gemfiles/rails_4.0.13.gemfile +0 -14
- data/gemfiles/rails_4.1.16.gemfile +0 -14
- data/gemfiles/rails_4.2.10.gemfile +0 -14
- data/lib/ajax-datatables-rails/config.rb +0 -31
- data/lib/ajax_datatables_rails.rb +0 -15
- data/lib/generators/datatable/config_generator.rb +0 -19
- data/lib/generators/datatable/templates/ajax_datatables_rails_config.rb +0 -12
- data/spec/ajax-datatables-rails/configuration_spec.rb +0 -43
- data/spec/ajax-datatables-rails/extended_spec.rb +0 -20
- data/spec/ajax-datatables-rails/orm/active_record_spec.rb +0 -25
@@ -1,12 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
|
-
describe AjaxDatatablesRails::ORM::ActiveRecord do
|
5
|
+
RSpec.describe AjaxDatatablesRails::ORM::ActiveRecord do
|
4
6
|
|
5
|
-
let(:
|
6
|
-
let(:datatable) { ComplexDatatable.new(view) }
|
7
|
+
let(:datatable) { ComplexDatatable.new(sample_params) }
|
7
8
|
let(:records) { User.all }
|
8
9
|
|
9
|
-
before
|
10
|
+
before do
|
10
11
|
create(:user, username: 'johndoe', email: 'johndoe@example.com')
|
11
12
|
create(:user, username: 'msmith', email: 'mary.smith@example.com')
|
12
13
|
end
|
@@ -17,8 +18,8 @@ describe AjaxDatatablesRails::ORM::ActiveRecord do
|
|
17
18
|
end
|
18
19
|
|
19
20
|
it 'paginates records properly' do
|
20
|
-
if
|
21
|
-
if Rails.version.in? %w[4.
|
21
|
+
if ENV['DB_ADAPTER'] == 'oracle_enhanced'
|
22
|
+
if Rails.version.in? %w[4.2.11]
|
22
23
|
expect(datatable.paginate_records(records).to_sql).to include(
|
23
24
|
'rownum <= 10'
|
24
25
|
)
|
@@ -35,8 +36,8 @@ describe AjaxDatatablesRails::ORM::ActiveRecord do
|
|
35
36
|
|
36
37
|
datatable.params[:start] = '26'
|
37
38
|
datatable.params[:length] = '25'
|
38
|
-
if
|
39
|
-
if Rails.version.in? %w[4.
|
39
|
+
if ENV['DB_ADAPTER'] == 'oracle_enhanced'
|
40
|
+
if Rails.version.in? %w[4.2.11]
|
40
41
|
expect(datatable.paginate_records(records).to_sql).to include(
|
41
42
|
'rownum <= 51'
|
42
43
|
)
|
@@ -1,13 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
|
-
describe AjaxDatatablesRails::ORM::ActiveRecord do
|
5
|
+
RSpec.describe AjaxDatatablesRails::ORM::ActiveRecord do
|
4
6
|
|
5
|
-
let(:
|
6
|
-
let(:
|
7
|
-
let(:nulls_last_datatable) { DatatableOrderNullsLast.new(view) }
|
7
|
+
let(:datatable) { ComplexDatatable.new(sample_params) }
|
8
|
+
let(:nulls_last_datatable) { DatatableOrderNullsLast.new(sample_params) }
|
8
9
|
let(:records) { User.all }
|
9
10
|
|
10
|
-
before
|
11
|
+
before do
|
11
12
|
create(:user, username: 'johndoe', email: 'johndoe@example.com')
|
12
13
|
create(:user, username: 'msmith', email: 'mary.smith@example.com')
|
13
14
|
end
|
@@ -31,7 +32,7 @@ describe AjaxDatatablesRails::ORM::ActiveRecord do
|
|
31
32
|
)
|
32
33
|
end
|
33
34
|
|
34
|
-
it '
|
35
|
+
it 'does not sort a column which is not orderable' do
|
35
36
|
datatable.params[:order]['0'] = { column: '0', dir: 'asc' }
|
36
37
|
datatable.params[:order]['1'] = { column: '4', dir: 'desc' }
|
37
38
|
|
@@ -46,30 +47,32 @@ describe AjaxDatatablesRails::ORM::ActiveRecord do
|
|
46
47
|
end
|
47
48
|
|
48
49
|
describe '#sort_records with nulls last using global config' do
|
49
|
-
before {
|
50
|
-
after {
|
51
|
-
|
50
|
+
before { datatable.nulls_last = true }
|
51
|
+
after { datatable.nulls_last = false }
|
52
|
+
|
52
53
|
it 'can handle multiple sorting columns' do
|
54
|
+
skip('unsupported database adapter') if ENV['DB_ADAPTER'] == 'oracle_enhanced'
|
55
|
+
|
53
56
|
# set to order by Users username in ascending order, and
|
54
57
|
# by Users email in descending order
|
55
58
|
datatable.params[:order]['0'] = { column: '0', dir: 'asc' }
|
56
59
|
datatable.params[:order]['1'] = { column: '1', dir: 'desc' }
|
57
60
|
expect(datatable.sort_records(records).to_sql).to include(
|
58
|
-
|
59
|
-
'CASE WHEN users.email IS NULL THEN 1 ELSE 0 END, users.email DESC'
|
61
|
+
"ORDER BY users.username ASC #{nulls_last_sql(datatable)}, users.email DESC #{nulls_last_sql(datatable)}"
|
60
62
|
)
|
61
63
|
end
|
62
64
|
end
|
63
|
-
|
65
|
+
|
64
66
|
describe '#sort_records with nulls last using column config' do
|
65
67
|
it 'can handle multiple sorting columns' do
|
68
|
+
skip('unsupported database adapter') if ENV['DB_ADAPTER'] == 'oracle_enhanced'
|
69
|
+
|
66
70
|
# set to order by Users username in ascending order, and
|
67
71
|
# by Users email in descending order
|
68
72
|
nulls_last_datatable.params[:order]['0'] = { column: '0', dir: 'asc' }
|
69
73
|
nulls_last_datatable.params[:order]['1'] = { column: '1', dir: 'desc' }
|
70
74
|
expect(nulls_last_datatable.sort_records(records).to_sql).to include(
|
71
|
-
|
72
|
-
'CASE WHEN users.email IS NULL THEN 1 ELSE 0 END, users.email DESC'
|
75
|
+
"ORDER BY users.username ASC, users.email DESC #{nulls_last_sql(datatable)}"
|
73
76
|
)
|
74
77
|
end
|
75
78
|
end
|
data/spec/factories/user.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
FactoryBot.define do
|
2
4
|
factory :user do |f|
|
3
5
|
f.username { Faker::Internet.user_name }
|
4
6
|
f.email { Faker::Internet.email }
|
5
7
|
f.first_name { Faker::Name.first_name }
|
6
8
|
f.last_name { Faker::Name.last_name }
|
7
|
-
f.post_id { (
|
9
|
+
f.post_id { (1..100).to_a.sample }
|
8
10
|
end
|
9
11
|
end
|
data/spec/install_oracle.sh
CHANGED
@@ -4,9 +4,15 @@ wget 'https://github.com/cbandy/travis-oracle/archive/v2.0.3.tar.gz'
|
|
4
4
|
mkdir -p ~/.travis/oracle
|
5
5
|
tar xz --strip-components 1 -C ~/.travis/oracle -f v2.0.3.tar.gz
|
6
6
|
|
7
|
-
|
7
|
+
if [ -n ${CUSTOM_ORACLE_FILE} ]; then
|
8
|
+
wget -q ${CUSTOM_ORACLE_FILE} -O ~/.travis/oracle/oracle-xe-11.2.0-1.0.x86_64.rpm.zip
|
9
|
+
else
|
10
|
+
~/.travis/oracle/download.sh
|
11
|
+
fi
|
12
|
+
|
8
13
|
~/.travis/oracle/install.sh
|
9
14
|
|
10
|
-
|
11
|
-
|
15
|
+
# in dev env: sqlplus system/password@localhost/XE
|
16
|
+
"${ORACLE_HOME}/bin/sqlplus" -L -S / AS SYSDBA <<SQL
|
17
|
+
ALTER USER ${USER} IDENTIFIED BY ${USER};
|
12
18
|
SQL
|
data/spec/spec_helper.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'simplecov'
|
2
4
|
require 'rspec'
|
5
|
+
require 'rspec/retry'
|
3
6
|
require 'database_cleaner'
|
4
7
|
require 'factory_bot'
|
5
8
|
require 'faker'
|
@@ -21,13 +24,6 @@ RSpec.configure do |config|
|
|
21
24
|
FactoryBot.find_definitions
|
22
25
|
end
|
23
26
|
|
24
|
-
config.after(:each) do
|
25
|
-
AjaxDatatablesRails.configure do |c|
|
26
|
-
c.db_adapter = ActiveRecord::Base.connection.adapter_name.downcase.to_sym
|
27
|
-
c.orm = :active_record
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
27
|
config.color = true
|
32
28
|
config.fail_fast = false
|
33
29
|
|
@@ -42,45 +38,54 @@ RSpec.configure do |config|
|
|
42
38
|
DatabaseCleaner.clean_with(:truncation)
|
43
39
|
end
|
44
40
|
|
45
|
-
config.before
|
41
|
+
config.before do
|
46
42
|
DatabaseCleaner.strategy = :transaction
|
47
43
|
end
|
48
44
|
|
49
|
-
config.before
|
45
|
+
config.before do
|
50
46
|
DatabaseCleaner.start
|
51
47
|
end
|
52
48
|
|
53
|
-
config.after
|
49
|
+
config.after do
|
54
50
|
DatabaseCleaner.clean
|
55
51
|
end
|
56
|
-
end
|
57
52
|
|
58
|
-
|
53
|
+
# disable monkey patching
|
54
|
+
# see: https://relishapp.com/rspec/rspec-core/v/3-8/docs/configuration/zero-monkey-patching-mode
|
55
|
+
config.disable_monkey_patching!
|
59
56
|
|
57
|
+
if ENV.key?('GITHUB_ACTIONS')
|
58
|
+
config.around do |ex|
|
59
|
+
ex.run_with_retry retry: 3
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Configure ActiveRecord
|
60
65
|
adapter = ENV.fetch('DB_ADAPTER', 'postgresql')
|
61
66
|
|
62
67
|
options = {
|
63
68
|
adapter: adapter,
|
64
69
|
database: 'ajax_datatables_rails',
|
65
|
-
encoding: 'utf8'
|
70
|
+
encoding: 'utf8',
|
66
71
|
}
|
67
72
|
|
68
|
-
options =
|
69
|
-
|
70
|
-
|
73
|
+
options =
|
74
|
+
case adapter
|
75
|
+
when 'postgresql'
|
76
|
+
options.merge(host: '127.0.0.1', port: 5432, username: 'postgres', password: 'postgres')
|
77
|
+
when 'mysql2'
|
78
|
+
options.merge(host: '127.0.0.1', port: 3306, username: 'root', password: 'root')
|
79
|
+
when 'oracle_enhanced'
|
80
|
+
options.merge(host: '127.0.0.1/xe', username: ENV['USER'], password: ENV['USER'], database: 'xe')
|
81
|
+
when 'sqlite3'
|
82
|
+
options.merge(database: ':memory:')
|
83
|
+
end
|
71
84
|
|
72
85
|
ActiveRecord::Base.establish_connection(options)
|
73
86
|
|
74
|
-
|
75
|
-
|
76
|
-
c.orm = :active_record
|
77
|
-
end
|
87
|
+
# Require our gem
|
88
|
+
require 'ajax-datatables-rails'
|
78
89
|
|
79
|
-
|
80
|
-
|
81
|
-
load File.dirname(__FILE__) + '/support/datatable_cond_date.rb'
|
82
|
-
load File.dirname(__FILE__) + '/support/datatable_cond_numeric.rb'
|
83
|
-
load File.dirname(__FILE__) + '/support/datatable_cond_proc.rb'
|
84
|
-
load File.dirname(__FILE__) + '/support/datatable_cond_string.rb'
|
85
|
-
load File.dirname(__FILE__) + '/support/datatable_order_nulls_last.rb'
|
86
|
-
require File.dirname(__FILE__) + '/support/test_models.rb'
|
90
|
+
# Load test helpers
|
91
|
+
Dir[File.dirname(__FILE__) + '/support/**/*.rb'].sort.each { |f| require f }
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ComplexDatatable < AjaxDatatablesRails::ActiveRecord
|
4
|
+
def view_columns
|
5
|
+
@view_columns ||= {
|
6
|
+
username: { source: 'User.username' },
|
7
|
+
email: { source: 'User.email' },
|
8
|
+
first_name: { source: 'User.first_name' },
|
9
|
+
last_name: { source: 'User.last_name' },
|
10
|
+
post_id: { source: 'User.post_id', orderable: false },
|
11
|
+
created_at: { source: 'User.created_at' },
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
def data
|
16
|
+
records.map do |record|
|
17
|
+
{
|
18
|
+
username: record.username,
|
19
|
+
email: record.email,
|
20
|
+
first_name: record.first_name,
|
21
|
+
last_name: record.last_name,
|
22
|
+
post_id: record.post_id,
|
23
|
+
created_at: record.created_at,
|
24
|
+
}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_raw_records
|
29
|
+
User.all
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ComplexDatatableArray < ComplexDatatable
|
4
|
+
def data
|
5
|
+
records.map do |record|
|
6
|
+
[
|
7
|
+
record.username,
|
8
|
+
record.email,
|
9
|
+
record.first_name,
|
10
|
+
record.last_name,
|
11
|
+
record.post_id,
|
12
|
+
record.created_at,
|
13
|
+
]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class DatatableCondEq < ComplexDatatable
|
2
4
|
def view_columns
|
3
5
|
super.deep_merge(post_id: { cond: :eq })
|
@@ -42,7 +44,7 @@ end
|
|
42
44
|
|
43
45
|
class DatatableCondInWithRegex < DatatableCondIn
|
44
46
|
def view_columns
|
45
|
-
super.deep_merge(post_id: { cond: :in, use_regex: false, orderable: true,
|
47
|
+
super.deep_merge(post_id: { cond: :in, use_regex: false, orderable: true, formatter: ->(str) { cast_regex_value(str) } })
|
46
48
|
end
|
47
49
|
|
48
50
|
def cast_regex_value(value)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class DatatableCondStartWith < ComplexDatatable
|
2
4
|
def view_columns
|
3
5
|
super.deep_merge(first_name: { cond: :start_with })
|
@@ -22,6 +24,12 @@ class DatatableCondStringEq < ComplexDatatable
|
|
22
24
|
end
|
23
25
|
end
|
24
26
|
|
27
|
+
class DatatableCondStringIn < ComplexDatatable
|
28
|
+
def view_columns
|
29
|
+
super.deep_merge(email: { cond: :string_in, formatter: ->(o) { o.split('|') } })
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
25
33
|
class DatatableCondNullValue < ComplexDatatable
|
26
34
|
def view_columns
|
27
35
|
super.deep_merge(email: { cond: :null_value })
|
@@ -30,6 +38,6 @@ end
|
|
30
38
|
|
31
39
|
class DatatableWithFormater < ComplexDatatable
|
32
40
|
def view_columns
|
33
|
-
super.deep_merge(last_name: {
|
41
|
+
super.deep_merge(last_name: { formatter: ->(o) { o.upcase } })
|
34
42
|
end
|
35
43
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# rubocop:disable Metrics/MethodLength
|
2
4
|
def sample_params
|
3
5
|
ActionController::Parameters.new(
|
@@ -42,7 +44,7 @@ def sample_params
|
|
42
44
|
},
|
43
45
|
},
|
44
46
|
'order' => {
|
45
|
-
'0' => {'column' => '0', 'dir' => 'asc'}
|
47
|
+
'0' => { 'column' => '0', 'dir' => 'asc' },
|
46
48
|
},
|
47
49
|
'start' => '0', 'length' => '10', 'search' => {
|
48
50
|
'value' => '', 'regex' => 'false'
|
@@ -51,49 +53,22 @@ def sample_params
|
|
51
53
|
}
|
52
54
|
)
|
53
55
|
end
|
54
|
-
# rubocop:enable Metrics/MethodLength
|
55
|
-
|
56
|
-
class ComplexDatatable < AjaxDatatablesRails::Base
|
57
|
-
def view_columns
|
58
|
-
@view_columns ||= {
|
59
|
-
username: { source: 'User.username' },
|
60
|
-
email: { source: 'User.email' },
|
61
|
-
first_name: { source: 'User.first_name' },
|
62
|
-
last_name: { source: 'User.last_name' },
|
63
|
-
post_id: { source: 'User.post_id', orderable: false },
|
64
|
-
created_at: { source: 'User.created_at' },
|
65
|
-
}
|
66
|
-
end
|
67
56
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
first_name: record.first_name,
|
74
|
-
last_name: record.last_name,
|
75
|
-
post_id: record.post_id,
|
76
|
-
created_at: record.created_at,
|
77
|
-
}
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def get_raw_records
|
82
|
-
User.all
|
83
|
-
end
|
57
|
+
def sample_params_json
|
58
|
+
hash_params = sample_params.to_unsafe_h
|
59
|
+
hash_params['columns'] = hash_params['columns'].values
|
60
|
+
hash_params['order'] = hash_params['order'].values
|
61
|
+
ActionController::Parameters.new(hash_params)
|
84
62
|
end
|
63
|
+
# rubocop:enable Metrics/MethodLength
|
85
64
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
record.post_id,
|
95
|
-
record.created_at,
|
96
|
-
]
|
97
|
-
end
|
65
|
+
def nulls_last_sql(datatable)
|
66
|
+
case datatable.db_adapter
|
67
|
+
when :pg, :postgresql, :postgres, :oracle
|
68
|
+
'NULLS LAST'
|
69
|
+
when :mysql, :mysql2, :sqlite, :sqlite3
|
70
|
+
'IS NULL'
|
71
|
+
else
|
72
|
+
raise 'unsupported database adapter'
|
98
73
|
end
|
99
74
|
end
|