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.
- 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
@@ -5,19 +5,21 @@ module AjaxDatatablesRails
|
|
5
5
|
class Column
|
6
6
|
module Search
|
7
7
|
|
8
|
-
SMALLEST_PQ_INTEGER = -
|
9
|
-
LARGEST_PQ_INTEGER
|
8
|
+
SMALLEST_PQ_INTEGER = -2_147_483_648
|
9
|
+
LARGEST_PQ_INTEGER = 2_147_483_647
|
10
|
+
NOT_NULL_VALUE = '!NULL'
|
11
|
+
EMPTY_VALUE = ''
|
10
12
|
|
11
13
|
def searchable?
|
12
14
|
@view_column.fetch(:searchable, true)
|
13
15
|
end
|
14
16
|
|
15
17
|
def cond
|
16
|
-
@view_column
|
18
|
+
@view_column.fetch(:cond, :like)
|
17
19
|
end
|
18
20
|
|
19
21
|
def filter
|
20
|
-
@view_column[:cond].call(self,
|
22
|
+
@view_column[:cond].call(self, formatted_value)
|
21
23
|
end
|
22
24
|
|
23
25
|
def search
|
@@ -46,33 +48,39 @@ module AjaxDatatablesRails
|
|
46
48
|
# The solution is to bypass regex_search and use non_regex_search with :in operator
|
47
49
|
def regex_search
|
48
50
|
if use_regex?
|
49
|
-
::Arel::Nodes::Regexp.new((custom_field? ? field : table[field]), ::Arel::Nodes.build_quoted(
|
51
|
+
::Arel::Nodes::Regexp.new((custom_field? ? field : table[field]), ::Arel::Nodes.build_quoted(formatted_value))
|
50
52
|
else
|
51
53
|
non_regex_search
|
52
54
|
end
|
53
55
|
end
|
54
56
|
|
57
|
+
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity
|
55
58
|
def non_regex_search
|
56
59
|
case cond
|
57
60
|
when Proc
|
58
61
|
filter
|
59
62
|
when :eq, :not_eq, :lt, :gt, :lteq, :gteq, :in
|
60
|
-
|
61
|
-
when :null_value
|
62
|
-
null_value_search
|
63
|
+
searchable_integer? ? raw_search(cond) : empty_search
|
63
64
|
when :start_with
|
64
|
-
|
65
|
+
text_search("#{formatted_value}%")
|
65
66
|
when :end_with
|
66
|
-
|
67
|
+
text_search("%#{formatted_value}")
|
67
68
|
when :like
|
68
|
-
|
69
|
+
text_search("%#{formatted_value}%")
|
69
70
|
when :string_eq
|
70
71
|
raw_search(:eq)
|
72
|
+
when :string_in
|
73
|
+
raw_search(:in)
|
74
|
+
when :null_value
|
75
|
+
null_value_search
|
76
|
+
when :date_range
|
77
|
+
date_range_search
|
71
78
|
end
|
72
79
|
end
|
80
|
+
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity
|
73
81
|
|
74
82
|
def null_value_search
|
75
|
-
if
|
83
|
+
if formatted_value == NOT_NULL_VALUE
|
76
84
|
table[field].not_eq(nil)
|
77
85
|
else
|
78
86
|
table[field].eq(nil)
|
@@ -81,31 +89,38 @@ module AjaxDatatablesRails
|
|
81
89
|
|
82
90
|
def raw_search(cond)
|
83
91
|
if custom_field?
|
84
|
-
::Arel::Nodes::SqlLiteral.new(field).eq(
|
92
|
+
::Arel::Nodes::SqlLiteral.new(field).eq(formatted_value)
|
85
93
|
else
|
86
|
-
table[field].send(cond,
|
94
|
+
table[field].send(cond, formatted_value)
|
87
95
|
end
|
88
96
|
end
|
89
97
|
|
98
|
+
def text_search(value)
|
99
|
+
casted_column.matches(value)
|
100
|
+
end
|
101
|
+
|
90
102
|
def empty_search
|
91
|
-
casted_column.matches(
|
103
|
+
casted_column.matches(EMPTY_VALUE)
|
92
104
|
end
|
93
105
|
|
94
|
-
def
|
95
|
-
if
|
96
|
-
valids =
|
106
|
+
def searchable_integer?
|
107
|
+
if formatted_value.is_a?(Array)
|
108
|
+
valids = formatted_value.map { |v| integer?(v) && !out_of_range?(v) }
|
97
109
|
!valids.include?(false)
|
98
110
|
else
|
99
|
-
|
111
|
+
integer?(formatted_value) && !out_of_range?(formatted_value)
|
100
112
|
end
|
101
113
|
end
|
102
114
|
|
103
|
-
def
|
115
|
+
def out_of_range?(search_value)
|
104
116
|
Integer(search_value) > LARGEST_PQ_INTEGER || Integer(search_value) < SMALLEST_PQ_INTEGER
|
105
117
|
end
|
106
118
|
|
107
|
-
def
|
108
|
-
|
119
|
+
def integer?(string)
|
120
|
+
Integer(string)
|
121
|
+
true
|
122
|
+
rescue ArgumentError
|
123
|
+
false
|
109
124
|
end
|
110
125
|
|
111
126
|
end
|
@@ -2,11 +2,8 @@
|
|
2
2
|
|
3
3
|
module AjaxDatatablesRails
|
4
4
|
module Datatable
|
5
|
-
|
6
|
-
TRUE_VALUE = 'true'
|
7
|
-
|
8
5
|
class Datatable
|
9
|
-
attr_reader :
|
6
|
+
attr_reader :options
|
10
7
|
|
11
8
|
def initialize(datatable)
|
12
9
|
@datatable = datatable
|
@@ -43,7 +40,7 @@ module AjaxDatatablesRails
|
|
43
40
|
|
44
41
|
def columns
|
45
42
|
@columns ||= get_param(:columns).map do |index, column_options|
|
46
|
-
Column.new(datatable, index, column_options)
|
43
|
+
Column.new(@datatable, index, column_options)
|
47
44
|
end
|
48
45
|
end
|
49
46
|
|
@@ -70,13 +67,25 @@ module AjaxDatatablesRails
|
|
70
67
|
end
|
71
68
|
|
72
69
|
def get_param(param)
|
73
|
-
if
|
74
|
-
|
70
|
+
return {} if options[param].nil?
|
71
|
+
|
72
|
+
if options[param].is_a? Array
|
73
|
+
hash = {}
|
74
|
+
options[param].each_with_index { |value, index| hash[index] = value }
|
75
|
+
hash
|
75
76
|
else
|
76
77
|
options[param].to_unsafe_h.with_indifferent_access
|
77
78
|
end
|
78
79
|
end
|
79
80
|
|
81
|
+
def db_adapter
|
82
|
+
@datatable.db_adapter
|
83
|
+
end
|
84
|
+
|
85
|
+
def nulls_last
|
86
|
+
@datatable.nulls_last
|
87
|
+
end
|
88
|
+
|
80
89
|
end
|
81
90
|
end
|
82
91
|
end
|
@@ -4,19 +4,19 @@ module AjaxDatatablesRails
|
|
4
4
|
module Datatable
|
5
5
|
class SimpleOrder
|
6
6
|
|
7
|
-
|
7
|
+
DIRECTION_ASC = 'ASC'
|
8
|
+
DIRECTION_DESC = 'DESC'
|
9
|
+
DIRECTIONS = [DIRECTION_ASC, DIRECTION_DESC].freeze
|
8
10
|
|
9
11
|
def initialize(datatable, options = {})
|
10
|
-
@datatable
|
11
|
-
@options
|
12
|
+
@datatable = datatable
|
13
|
+
@options = options
|
14
|
+
@adapter = datatable.db_adapter
|
15
|
+
@nulls_last = datatable.nulls_last
|
12
16
|
end
|
13
17
|
|
14
18
|
def query(sort_column)
|
15
|
-
|
16
|
-
"CASE WHEN #{sort_column} IS NULL THEN 1 ELSE 0 END, #{sort_column} #{direction}"
|
17
|
-
else
|
18
|
-
"#{sort_column} #{direction}"
|
19
|
-
end
|
19
|
+
[sort_column, direction, nulls_last_sql].compact.join(' ')
|
20
20
|
end
|
21
21
|
|
22
22
|
def column
|
@@ -24,7 +24,7 @@ module AjaxDatatablesRails
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def direction
|
27
|
-
DIRECTIONS.find { |dir| dir == column_direction } ||
|
27
|
+
DIRECTIONS.find { |dir| dir == column_direction } || DIRECTION_ASC
|
28
28
|
end
|
29
29
|
|
30
30
|
private
|
@@ -38,7 +38,20 @@ module AjaxDatatablesRails
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def sort_nulls_last?
|
41
|
-
column.nulls_last? ||
|
41
|
+
column.nulls_last? || @nulls_last == true
|
42
|
+
end
|
43
|
+
|
44
|
+
def nulls_last_sql
|
45
|
+
return unless sort_nulls_last?
|
46
|
+
|
47
|
+
case @adapter
|
48
|
+
when :pg, :postgresql, :postgres, :oracle
|
49
|
+
'NULLS LAST'
|
50
|
+
when :mysql, :mysql2, :sqlite, :sqlite3
|
51
|
+
'IS NULL'
|
52
|
+
else
|
53
|
+
raise "unsupported database adapter: #{@adapter}"
|
54
|
+
end
|
42
55
|
end
|
43
56
|
|
44
57
|
end
|
@@ -4,15 +4,11 @@ module AjaxDatatablesRails
|
|
4
4
|
module ORM
|
5
5
|
module ActiveRecord
|
6
6
|
|
7
|
-
def fetch_records
|
8
|
-
get_raw_records
|
9
|
-
end
|
10
|
-
|
11
7
|
def filter_records(records)
|
12
8
|
records.where(build_conditions)
|
13
9
|
end
|
14
10
|
|
15
|
-
# rubocop:disable Style/EachWithObject
|
11
|
+
# rubocop:disable Style/EachWithObject, Style/SafeNavigation
|
16
12
|
def sort_records(records)
|
17
13
|
sort_by = datatable.orders.inject([]) do |queries, order|
|
18
14
|
column = order.column
|
@@ -21,7 +17,7 @@ module AjaxDatatablesRails
|
|
21
17
|
end
|
22
18
|
records.order(Arel.sql(sort_by.join(', ')))
|
23
19
|
end
|
24
|
-
# rubocop:enable Style/EachWithObject
|
20
|
+
# rubocop:enable Style/EachWithObject, Style/SafeNavigation
|
25
21
|
|
26
22
|
def paginate_records(records)
|
27
23
|
records.offset(datatable.offset).limit(datatable.per_page)
|
@@ -30,23 +26,26 @@ module AjaxDatatablesRails
|
|
30
26
|
# ----------------- SEARCH HELPER METHODS --------------------
|
31
27
|
|
32
28
|
def build_conditions
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
29
|
+
@build_conditions ||= begin
|
30
|
+
criteria = [build_conditions_for_selected_columns]
|
31
|
+
criteria << build_conditions_for_datatable if datatable.searchable?
|
32
|
+
criteria.compact.reduce(:and)
|
37
33
|
end
|
38
34
|
end
|
39
35
|
|
36
|
+
# rubocop:disable Metrics/AbcSize
|
40
37
|
def build_conditions_for_datatable
|
38
|
+
columns = searchable_columns.reject(&:searched?)
|
41
39
|
criteria = search_for.inject([]) do |crit, atom|
|
42
40
|
search = Datatable::SimpleSearch.new(value: atom, regex: datatable.search.regexp?)
|
43
|
-
crit <<
|
41
|
+
crit << columns.map do |simple_column|
|
44
42
|
simple_column.search = search
|
45
43
|
simple_column.search_query
|
46
|
-
end.reduce(:or)
|
44
|
+
end.compact.reduce(:or)
|
47
45
|
end.compact.reduce(:and)
|
48
46
|
criteria
|
49
47
|
end
|
48
|
+
# rubocop:enable Metrics/AbcSize
|
50
49
|
|
51
50
|
def build_conditions_for_selected_columns
|
52
51
|
search_columns.map(&:search_query).compact.reduce(:and)
|
@@ -1,5 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module AjaxDatatablesRails
|
4
|
-
|
4
|
+
|
5
|
+
def self.gem_version
|
6
|
+
Gem::Version.new VERSION::STRING
|
7
|
+
end
|
8
|
+
|
9
|
+
module VERSION
|
10
|
+
MAJOR = 1
|
11
|
+
MINOR = 3
|
12
|
+
TINY = 1
|
13
|
+
PRE = nil
|
14
|
+
|
15
|
+
STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
|
16
|
+
end
|
5
17
|
end
|
@@ -1,54 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
|
-
describe AjaxDatatablesRails::Base do
|
5
|
+
RSpec.describe AjaxDatatablesRails::Base do
|
4
6
|
|
5
7
|
describe 'an instance' do
|
6
|
-
|
7
|
-
|
8
|
-
it 'requires a view_context' do
|
8
|
+
it 'requires a hash of params' do
|
9
9
|
expect { described_class.new }.to raise_error ArgumentError
|
10
10
|
end
|
11
11
|
|
12
12
|
it 'accepts an options hash' do
|
13
|
-
datatable = described_class.new(
|
13
|
+
datatable = described_class.new(sample_params, foo: 'bar')
|
14
14
|
expect(datatable.options).to eq(foo: 'bar')
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
|
19
|
-
let(:view) { double('view', params: sample_params) }
|
20
|
-
|
18
|
+
describe 'User API' do
|
21
19
|
describe '#view_columns' do
|
22
|
-
|
23
|
-
|
24
|
-
|
20
|
+
context 'when method is not defined by the user' do
|
21
|
+
it 'raises an error' do
|
22
|
+
datatable = described_class.new(sample_params)
|
23
|
+
expect { datatable.view_columns }.to raise_error NotImplementedError
|
24
|
+
end
|
25
25
|
end
|
26
26
|
|
27
27
|
context 'child class implements view_columns' do
|
28
28
|
it 'expects a hash based defining columns' do
|
29
|
-
datatable = ComplexDatatable.new(
|
29
|
+
datatable = ComplexDatatable.new(sample_params)
|
30
30
|
expect(datatable.view_columns).to be_a(Hash)
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
35
|
describe '#get_raw_records' do
|
36
|
-
|
37
|
-
|
38
|
-
|
36
|
+
context 'when method is not defined by the user' do
|
37
|
+
it 'raises an error' do
|
38
|
+
datatable = described_class.new(sample_params)
|
39
|
+
expect { datatable.get_raw_records }.to raise_error NotImplementedError
|
40
|
+
end
|
39
41
|
end
|
40
42
|
end
|
41
43
|
|
42
44
|
describe '#data' do
|
43
|
-
|
44
|
-
|
45
|
-
|
45
|
+
context 'when method is not defined by the user' do
|
46
|
+
it 'raises an error' do
|
47
|
+
datatable = described_class.new(sample_params)
|
48
|
+
expect { datatable.data }.to raise_error NotImplementedError
|
49
|
+
end
|
46
50
|
end
|
47
51
|
|
48
52
|
context 'when data is defined as a hash' do
|
49
|
-
let(:datatable) { ComplexDatatable.new(
|
53
|
+
let(:datatable) { ComplexDatatable.new(sample_params) }
|
50
54
|
|
51
|
-
it '
|
55
|
+
it 'returns an array of hashes' do
|
52
56
|
create_list(:user, 5)
|
53
57
|
expect(datatable.data).to be_a(Array)
|
54
58
|
expect(datatable.data.size).to eq 5
|
@@ -56,9 +60,9 @@ describe AjaxDatatablesRails::Base do
|
|
56
60
|
expect(item).to be_a(Hash)
|
57
61
|
end
|
58
62
|
|
59
|
-
it '
|
63
|
+
it 'htmls escape data' do
|
60
64
|
create(:user, first_name: 'Name "><img src=x onerror=alert("first_name")>', last_name: 'Name "><img src=x onerror=alert("last_name")>')
|
61
|
-
data = datatable.send(:
|
65
|
+
data = datatable.send(:sanitize_data, datatable.data)
|
62
66
|
item = data.first
|
63
67
|
expect(item[:first_name]).to eq 'Name "><img src=x onerror=alert("first_name")>'
|
64
68
|
expect(item[:last_name]).to eq 'Name "><img src=x onerror=alert("last_name")>'
|
@@ -66,9 +70,9 @@ describe AjaxDatatablesRails::Base do
|
|
66
70
|
end
|
67
71
|
|
68
72
|
context 'when data is defined as a array' do
|
69
|
-
let(:datatable) { ComplexDatatableArray.new(
|
73
|
+
let(:datatable) { ComplexDatatableArray.new(sample_params) }
|
70
74
|
|
71
|
-
it '
|
75
|
+
it 'returns an array of arrays' do
|
72
76
|
create_list(:user, 5)
|
73
77
|
expect(datatable.data).to be_a(Array)
|
74
78
|
expect(datatable.data.size).to eq 5
|
@@ -76,20 +80,103 @@ describe AjaxDatatablesRails::Base do
|
|
76
80
|
expect(item).to be_a(Array)
|
77
81
|
end
|
78
82
|
|
79
|
-
it '
|
83
|
+
it 'htmls escape data' do
|
80
84
|
create(:user, first_name: 'Name "><img src=x onerror=alert("first_name")>', last_name: 'Name "><img src=x onerror=alert("last_name")>')
|
81
|
-
data = datatable.send(:
|
85
|
+
data = datatable.send(:sanitize_data, datatable.data)
|
82
86
|
item = data.first
|
83
87
|
expect(item[2]).to eq 'Name "><img src=x onerror=alert("first_name")>'
|
84
88
|
expect(item[3]).to eq 'Name "><img src=x onerror=alert("last_name")>'
|
85
89
|
end
|
86
90
|
end
|
87
91
|
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe 'ORM API' do
|
95
|
+
context 'when ORM is not implemented' do
|
96
|
+
let(:datatable) { AjaxDatatablesRails::Base.new(sample_params) }
|
97
|
+
|
98
|
+
describe '#fetch_records' do
|
99
|
+
it 'raises an error if it does not include an ORM module' do
|
100
|
+
expect { datatable.fetch_records }.to raise_error NotImplementedError
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe '#filter_records' do
|
105
|
+
it 'raises an error if it does not include an ORM module' do
|
106
|
+
expect { datatable.filter_records([]) }.to raise_error NotImplementedError
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe '#sort_records' do
|
111
|
+
it 'raises an error if it does not include an ORM module' do
|
112
|
+
expect { datatable.sort_records([]) }.to raise_error NotImplementedError
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe '#paginate_records' do
|
117
|
+
it 'raises an error if it does not include an ORM module' do
|
118
|
+
expect { datatable.paginate_records([]) }.to raise_error NotImplementedError
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
context 'when ORM is implemented' do
|
124
|
+
describe 'it allows method override' do
|
125
|
+
let(:datatable) do
|
126
|
+
datatable = Class.new(ComplexDatatable) do
|
127
|
+
def filter_records(records)
|
128
|
+
raise NotImplementedError.new('FOO')
|
129
|
+
end
|
130
|
+
|
131
|
+
def sort_records(records)
|
132
|
+
raise NotImplementedError.new('FOO')
|
133
|
+
end
|
134
|
+
|
135
|
+
def paginate_records(records)
|
136
|
+
raise NotImplementedError.new('FOO')
|
137
|
+
end
|
138
|
+
end
|
139
|
+
datatable.new(sample_params)
|
140
|
+
end
|
141
|
+
|
142
|
+
describe '#fetch_records' do
|
143
|
+
it 'calls #get_raw_records' do
|
144
|
+
expect(datatable).to receive(:get_raw_records) { User.all }
|
145
|
+
datatable.fetch_records
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'returns a collection of records' do
|
149
|
+
expect(datatable).to receive(:get_raw_records) { User.all }
|
150
|
+
expect(datatable.fetch_records).to be_a(ActiveRecord::Relation)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
describe '#filter_records' do
|
155
|
+
it {
|
156
|
+
expect { datatable.filter_records([]) }.to raise_error(NotImplementedError).with_message('FOO')
|
157
|
+
}
|
158
|
+
end
|
159
|
+
|
160
|
+
describe '#sort_records' do
|
161
|
+
it {
|
162
|
+
expect { datatable.sort_records([]) }.to raise_error(NotImplementedError).with_message('FOO')
|
163
|
+
}
|
164
|
+
end
|
165
|
+
|
166
|
+
describe '#paginate_records' do
|
167
|
+
it {
|
168
|
+
expect { datatable.paginate_records([]) }.to raise_error(NotImplementedError).with_message('FOO')
|
169
|
+
}
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
88
174
|
|
175
|
+
describe 'JSON format' do
|
89
176
|
describe '#as_json' do
|
90
|
-
let(:datatable) { ComplexDatatable.new(
|
177
|
+
let(:datatable) { ComplexDatatable.new(sample_params) }
|
91
178
|
|
92
|
-
it '
|
179
|
+
it 'returns a hash' do
|
93
180
|
create_list(:user, 5)
|
94
181
|
data = datatable.as_json
|
95
182
|
expect(data[:recordsTotal]).to eq 5
|
@@ -99,9 +186,9 @@ describe AjaxDatatablesRails::Base do
|
|
99
186
|
end
|
100
187
|
|
101
188
|
context 'with additional_data' do
|
102
|
-
it '
|
189
|
+
it 'returns a hash' do
|
103
190
|
create_list(:user, 5)
|
104
|
-
expect(datatable).to receive(:additional_data){ { foo: 'bar' } }
|
191
|
+
expect(datatable).to receive(:additional_data) { { foo: 'bar' } }
|
105
192
|
data = datatable.as_json
|
106
193
|
expect(data[:recordsTotal]).to eq 5
|
107
194
|
expect(data[:recordsFiltered]).to eq 5
|
@@ -113,74 +200,23 @@ describe AjaxDatatablesRails::Base do
|
|
113
200
|
end
|
114
201
|
end
|
115
202
|
|
203
|
+
describe 'User helper methods' do
|
204
|
+
describe '#column_id' do
|
205
|
+
let(:datatable) { ComplexDatatable.new(sample_params) }
|
116
206
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
let(:datatable) { ComplexDatatable.new(view) }
|
121
|
-
|
122
|
-
before(:each) do
|
123
|
-
allow_any_instance_of(AjaxDatatablesRails::Configuration).to receive(:orm) { nil }
|
124
|
-
end
|
125
|
-
|
126
|
-
describe '#fetch_records' do
|
127
|
-
it 'raises an error if it does not include an ORM module' do
|
128
|
-
expect { datatable.send(:fetch_records) }.to raise_error NoMethodError
|
207
|
+
it 'returns column id from view_columns hash' do
|
208
|
+
expect(datatable.column_id(:username)).to eq(0)
|
209
|
+
expect(datatable.column_id('username')).to eq(0)
|
129
210
|
end
|
130
211
|
end
|
131
212
|
|
132
|
-
describe '#
|
133
|
-
|
134
|
-
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
describe '#sort_records' do
|
139
|
-
it 'raises an error if it does not include an ORM module' do
|
140
|
-
expect { datatable.send(:sort_records) }.to raise_error NoMethodError
|
141
|
-
end
|
142
|
-
end
|
213
|
+
describe '#column_data' do
|
214
|
+
let(:datatable) { ComplexDatatable.new(sample_params) }
|
215
|
+
before { datatable.params[:columns]['0'][:search][:value] = 'doe' }
|
143
216
|
|
144
|
-
|
145
|
-
|
146
|
-
expect
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
describe 'helper methods' do
|
151
|
-
describe '#offset' do
|
152
|
-
it 'defaults to 0' do
|
153
|
-
default_view = double('view', params: {})
|
154
|
-
datatable = described_class.new(default_view)
|
155
|
-
expect(datatable.datatable.send(:offset)).to eq(0)
|
156
|
-
end
|
157
|
-
|
158
|
-
it 'matches the value on view params[:start]' do
|
159
|
-
paginated_view = double('view', params: { start: '11' })
|
160
|
-
datatable = described_class.new(paginated_view)
|
161
|
-
expect(datatable.datatable.send(:offset)).to eq(11)
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
describe '#page' do
|
166
|
-
it 'calculates page number from params[:start] and #per_page' do
|
167
|
-
paginated_view = double('view', params: { start: '11' })
|
168
|
-
datatable = described_class.new(paginated_view)
|
169
|
-
expect(datatable.datatable.send(:page)).to eq(2)
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
describe '#per_page' do
|
174
|
-
it 'defaults to 10' do
|
175
|
-
datatable = described_class.new(view)
|
176
|
-
expect(datatable.datatable.send(:per_page)).to eq(10)
|
177
|
-
end
|
178
|
-
|
179
|
-
it 'matches the value on view params[:length]' do
|
180
|
-
other_view = double('view', params: { length: 20 })
|
181
|
-
datatable = described_class.new(other_view)
|
182
|
-
expect(datatable.datatable.send(:per_page)).to eq(20)
|
183
|
-
end
|
217
|
+
it 'returns column data from params' do
|
218
|
+
expect(datatable.column_data(:username)).to eq('doe')
|
219
|
+
expect(datatable.column_data('username')).to eq('doe')
|
184
220
|
end
|
185
221
|
end
|
186
222
|
end
|