effective_datatables 2.12.2 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +632 -512
- data/app/assets/javascripts/dataTables/buttons/buttons.html5.js +176 -177
- data/app/assets/javascripts/dataTables/buttons/buttons.print.js +2 -0
- data/app/assets/javascripts/dataTables/buttons/dataTables.buttons.js +14 -14
- data/app/assets/javascripts/dataTables/dataTables.bootstrap.js +1 -1
- data/app/assets/javascripts/dataTables/jquery.dataTables.js +246 -217
- data/app/assets/javascripts/effective_datatables.js +2 -3
- data/app/assets/javascripts/effective_datatables/events.js.coffee +7 -0
- data/app/assets/javascripts/effective_datatables/filters.js.coffee +6 -0
- data/app/assets/javascripts/effective_datatables/initialize.js.coffee +42 -39
- data/app/assets/javascripts/effective_datatables/reset.js.coffee +7 -0
- data/app/assets/javascripts/vendor/jquery.delayedChange.js +1 -1
- data/app/assets/stylesheets/dataTables/dataTables.bootstrap.css +0 -1
- data/app/assets/stylesheets/effective_datatables.scss +1 -2
- data/app/assets/stylesheets/effective_datatables/{_scopes.scss → _filters.scss} +1 -1
- data/app/assets/stylesheets/effective_datatables/_overrides.scss +1 -1
- data/app/controllers/effective/datatables_controller.rb +2 -4
- data/app/helpers/effective_datatables_helper.rb +56 -91
- data/app/helpers/effective_datatables_private_helper.rb +55 -64
- data/app/models/effective/datatable.rb +103 -177
- data/app/models/effective/datatable_column.rb +28 -0
- data/app/models/effective/datatable_column_tool.rb +110 -0
- data/app/models/effective/datatable_dsl_tool.rb +28 -0
- data/app/models/effective/datatable_value_tool.rb +142 -0
- data/app/models/effective/effective_datatable/attributes.rb +25 -0
- data/app/models/effective/effective_datatable/collection.rb +38 -0
- data/app/models/effective/effective_datatable/compute.rb +154 -0
- data/app/models/effective/effective_datatable/cookie.rb +29 -0
- data/app/models/effective/effective_datatable/dsl.rb +14 -8
- data/app/models/effective/effective_datatable/dsl/bulk_actions.rb +5 -6
- data/app/models/effective/effective_datatable/dsl/charts.rb +7 -9
- data/app/models/effective/effective_datatable/dsl/datatable.rb +107 -57
- data/app/models/effective/effective_datatable/dsl/filters.rb +50 -0
- data/app/models/effective/effective_datatable/format.rb +157 -0
- data/app/models/effective/effective_datatable/hooks.rb +0 -18
- data/app/models/effective/effective_datatable/params.rb +34 -0
- data/app/models/effective/effective_datatable/resource.rb +108 -0
- data/app/models/effective/effective_datatable/state.rb +178 -0
- data/app/views/effective/datatables/_actions_column.html.haml +9 -42
- data/app/views/effective/datatables/_bulk_actions_column.html.haml +1 -1
- data/app/views/effective/datatables/_bulk_actions_dropdown.html.haml +2 -3
- data/app/views/effective/datatables/_chart.html.haml +1 -1
- data/app/views/effective/datatables/_datatable.html.haml +7 -25
- data/app/views/effective/datatables/_filters.html.haml +21 -0
- data/app/views/effective/datatables/_reset.html.haml +2 -0
- data/app/views/effective/datatables/_resource_column.html.haml +8 -0
- data/app/views/effective/datatables/index.html.haml +0 -1
- data/config/effective_datatables.rb +9 -32
- data/lib/effective_datatables.rb +2 -6
- data/lib/effective_datatables/engine.rb +1 -1
- data/lib/effective_datatables/version.rb +1 -1
- data/lib/generators/effective_datatables/install_generator.rb +2 -2
- metadata +39 -19
- data/app/assets/javascripts/dataTables/colreorder/dataTables.colReorder.js +0 -27
- data/app/assets/javascripts/dataTables/jszip/jszip.js +0 -9155
- data/app/assets/javascripts/effective_datatables/scopes.js.coffee +0 -9
- data/app/models/effective/active_record_datatable_tool.rb +0 -242
- data/app/models/effective/array_datatable_tool.rb +0 -97
- data/app/models/effective/effective_datatable/ajax.rb +0 -101
- data/app/models/effective/effective_datatable/charts.rb +0 -20
- data/app/models/effective/effective_datatable/dsl/scopes.rb +0 -23
- data/app/models/effective/effective_datatable/helpers.rb +0 -24
- data/app/models/effective/effective_datatable/options.rb +0 -309
- data/app/models/effective/effective_datatable/rendering.rb +0 -365
- data/app/views/effective/datatables/_scopes.html.haml +0 -21
@@ -1,112 +1,103 @@
|
|
1
|
-
# These aren't expected to be called by a developer.
|
2
|
-
# They are internal datatables methods, but you could still call them on the view.
|
1
|
+
# These aren't expected to be called by a developer. They are internal methods.
|
3
2
|
module EffectiveDatatablesPrivateHelper
|
4
3
|
|
5
|
-
def datatable_default_order(datatable)
|
6
|
-
[datatable.order_index, datatable.order_direction.downcase].to_json()
|
7
|
-
end
|
8
|
-
|
9
4
|
# https://datatables.net/reference/option/columns
|
10
5
|
def datatable_columns(datatable)
|
11
6
|
form = nil
|
12
|
-
simple_form_for(:
|
7
|
+
simple_form_for(:datatable_search, url: '#', html: {id: "#{datatable.to_param}-form"}) { |f| form = f }
|
13
8
|
|
14
|
-
datatable.
|
9
|
+
datatable.columns.map do |name, opts|
|
15
10
|
{
|
16
|
-
name:
|
17
|
-
title: content_tag(:span,
|
18
|
-
className:
|
19
|
-
|
20
|
-
responsivePriority:
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
filterSelectedValue: options[:filter][:selected]
|
11
|
+
name: name,
|
12
|
+
title: content_tag(:span, opts[:label], class: 'search-label'),
|
13
|
+
className: opts[:col_class],
|
14
|
+
searchHtml: (datatable_search_html(form, name, datatable.state[:search][name], opts) unless datatable.simple?),
|
15
|
+
responsivePriority: opts[:responsive],
|
16
|
+
search: datatable.state[:search][name],
|
17
|
+
sortable: (opts[:sort] && !datatable.simple?),
|
18
|
+
visible: datatable.state[:visible][name],
|
25
19
|
}
|
26
|
-
end.to_json
|
20
|
+
end.to_json
|
27
21
|
end
|
28
22
|
|
29
23
|
def datatable_bulk_actions(datatable)
|
30
|
-
|
31
|
-
|
24
|
+
render(partial: '/effective/datatables/bulk_actions_dropdown', locals: { datatable: datatable }) if datatable._bulk_actions.present?
|
25
|
+
end
|
32
26
|
|
33
|
-
|
34
|
-
|
35
|
-
partial: bulk_actions_column[:dropdown_partial],
|
36
|
-
locals: { datatable: datatable, dropdown_block: bulk_actions_column[:dropdown_block] }.merge(bulk_actions_column[:partial_locals])
|
37
|
-
)
|
38
|
-
}.to_json()
|
27
|
+
def datatable_reset(datatable)
|
28
|
+
render(partial: '/effective/datatables/reset', locals: { datatable: datatable })
|
39
29
|
end
|
40
30
|
|
41
|
-
def
|
42
|
-
|
31
|
+
def datatable_search_html(form, name, value, opts)
|
32
|
+
include_blank = opts[:search].key?(:include_blank) ? opts[:search][:include_blank] : opts[:label]
|
33
|
+
pattern = opts[:search][:pattern]
|
34
|
+
placeholder = opts[:search][:placeholder] || ''
|
35
|
+
title = opts[:search][:title] || opts[:label]
|
36
|
+
wrapper_html = { class: 'datatable_search' }
|
43
37
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
38
|
+
input_html = {
|
39
|
+
name: nil,
|
40
|
+
value: value,
|
41
|
+
title: title,
|
42
|
+
pattern: pattern,
|
43
|
+
autocomplete: 'off',
|
44
|
+
data: {'column-name' => name, 'column-index' => opts[:index]}
|
45
|
+
}.delete_if { |k, v| v.blank? && k != :name }
|
49
46
|
|
50
|
-
case opts[:
|
47
|
+
case opts[:search][:as]
|
51
48
|
when :string, :text, :number
|
52
49
|
form.input name, label: false, required: false, value: value,
|
53
50
|
as: :string,
|
54
51
|
placeholder: placeholder,
|
55
52
|
wrapper_html: wrapper_html,
|
56
|
-
input_html:
|
57
|
-
when :
|
58
|
-
pattern ||= '[0-9]{3}-?[0-9]{4}-?[0-9]{3}'
|
59
|
-
|
53
|
+
input_html: input_html
|
54
|
+
when :effective_obfuscation
|
55
|
+
input_html[:pattern] ||= '[0-9]{3}-?[0-9]{4}-?[0-9]{3}'
|
56
|
+
input_html[:title] = 'Expected format: XXX-XXXX-XXX'
|
60
57
|
|
61
58
|
form.input name, label: false, required: false, value: value,
|
62
59
|
as: :string,
|
63
|
-
placeholder: placeholder
|
60
|
+
placeholder: placeholder,
|
64
61
|
wrapper_html: wrapper_html,
|
65
|
-
input_html:
|
66
|
-
when :date
|
62
|
+
input_html: input_html
|
63
|
+
when :date, :datetime
|
67
64
|
form.input name, label: false, required: false, value: value,
|
68
65
|
as: (ActionView::Helpers::FormBuilder.instance_methods.include?(:effective_date_picker) ? :effective_date_picker : :string),
|
69
66
|
placeholder: placeholder,
|
70
67
|
wrapper_html: wrapper_html,
|
71
68
|
input_group: false,
|
72
|
-
input_html:
|
69
|
+
input_html: input_html,
|
73
70
|
input_js: { useStrict: true, keepInvalid: true }
|
74
|
-
|
75
|
-
form.input name, label: false, required: false, value: value,
|
76
|
-
as: (ActionView::Helpers::FormBuilder.instance_methods.include?(:effective_date_time_picker) ? :effective_date_time_picker : :string),
|
77
|
-
placeholder: placeholder,
|
78
|
-
wrapper_html: wrapper_html,
|
79
|
-
input_group: false,
|
80
|
-
input_html: { name: nil, value: value, title: title, autocomplete: 'off', data: {'column-name' => opts[:name], 'column-index' => opts[:index]} },
|
81
|
-
input_js: { useStrict: true, keepInvalid: true } # Keep invalid format like "2015-11" so we can still filter by year, month or day
|
71
|
+
# Keep invalid format like "2015-11" so we can still search by year, month or day
|
82
72
|
when :select, :boolean
|
83
73
|
form.input name, label: false, required: false, value: value,
|
84
74
|
as: (ActionView::Helpers::FormBuilder.instance_methods.include?(:effective_select) ? :effective_select : :select),
|
85
|
-
collection: opts[:
|
86
|
-
selected: opts[:
|
87
|
-
multiple: opts[:
|
75
|
+
collection: opts[:search][:collection],
|
76
|
+
selected: opts[:search][:value],
|
77
|
+
multiple: opts[:search][:multiple] == true,
|
88
78
|
include_blank: include_blank,
|
89
79
|
wrapper_html: wrapper_html,
|
90
|
-
input_html:
|
80
|
+
input_html: input_html,
|
91
81
|
input_js: { placeholder: placeholder }
|
92
82
|
when :grouped_select
|
93
83
|
form.input name, label: false, required: false, value: value,
|
94
84
|
as: (ActionView::Helpers::FormBuilder.instance_methods.include?(:effective_select) ? :effective_select : :grouped_select),
|
95
|
-
collection: opts[:
|
96
|
-
selected: opts[:
|
97
|
-
multiple: opts[:
|
98
|
-
include_blank: include_blank,
|
85
|
+
collection: opts[:search][:collection],
|
86
|
+
selected: opts[:search][:value],
|
87
|
+
multiple: opts[:search][:multiple] == true,
|
99
88
|
grouped: true,
|
100
|
-
polymorphic: opts[:
|
101
|
-
group_label_method: opts[:
|
102
|
-
group_method: opts[:
|
89
|
+
polymorphic: opts[:search][:polymorphic] == true,
|
90
|
+
group_label_method: opts[:search][:group_label_method] || :first,
|
91
|
+
group_method: opts[:search][:group_method] || :last,
|
103
92
|
wrapper_html: wrapper_html,
|
104
|
-
input_html:
|
93
|
+
input_html: input_html,
|
105
94
|
input_js: { placeholder: placeholder }
|
106
|
-
when :
|
95
|
+
when :bulk_actions
|
96
|
+
input_html[:data]['role'] = 'bulk-actions-all'
|
97
|
+
|
107
98
|
form.input name, label: false, required: false, value: nil,
|
108
99
|
as: :boolean,
|
109
|
-
input_html:
|
100
|
+
input_html: input_html
|
110
101
|
end
|
111
102
|
end
|
112
103
|
|
@@ -1,234 +1,160 @@
|
|
1
1
|
module Effective
|
2
2
|
class Datatable
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
attr_reader :attributes # Anything that we initialize our table with. That's it. Can't be changed by state.
|
4
|
+
attr_reader :resource
|
5
|
+
attr_reader :state
|
6
|
+
|
7
|
+
# Hashes of DSL options
|
8
|
+
attr_reader :_aggregates
|
9
|
+
attr_reader :_bulk_actions
|
10
|
+
attr_reader :_charts
|
11
|
+
attr_reader :_columns
|
12
|
+
attr_reader :_filters
|
13
|
+
attr_reader :_form
|
14
|
+
attr_reader :_scopes
|
15
|
+
|
16
|
+
# The collection itself. Only evaluated once.
|
17
|
+
attr_accessor :_collection
|
18
|
+
|
19
|
+
# The view, and the ajax/cookie/default state
|
20
|
+
attr_reader :cookie
|
21
|
+
attr_reader :view
|
9
22
|
|
10
23
|
extend Effective::EffectiveDatatable::Dsl
|
11
24
|
|
12
|
-
include Effective::EffectiveDatatable::
|
13
|
-
include Effective::EffectiveDatatable::
|
14
|
-
include Effective::EffectiveDatatable::
|
15
|
-
include Effective::EffectiveDatatable::
|
16
|
-
|
17
|
-
include Effective::EffectiveDatatable::Ajax
|
18
|
-
include Effective::EffectiveDatatable::Charts
|
19
|
-
include Effective::EffectiveDatatable::Helpers
|
25
|
+
include Effective::EffectiveDatatable::Attributes
|
26
|
+
include Effective::EffectiveDatatable::Collection
|
27
|
+
include Effective::EffectiveDatatable::Compute
|
28
|
+
include Effective::EffectiveDatatable::Cookie
|
29
|
+
include Effective::EffectiveDatatable::Format
|
20
30
|
include Effective::EffectiveDatatable::Hooks
|
21
|
-
include Effective::EffectiveDatatable::
|
22
|
-
include Effective::EffectiveDatatable::
|
23
|
-
|
24
|
-
def initialize(*args)
|
25
|
-
initialize_attributes(args)
|
31
|
+
include Effective::EffectiveDatatable::Params
|
32
|
+
include Effective::EffectiveDatatable::Resource
|
33
|
+
include Effective::EffectiveDatatable::State
|
26
34
|
|
27
|
-
|
28
|
-
|
29
|
-
initialize_scope_options
|
30
|
-
end
|
31
|
-
|
32
|
-
if respond_to?(:initialize_datatable)
|
33
|
-
initialize_datatable # This creates @table_columns based on the DSL datatable do .. end block
|
34
|
-
initialize_datatable_options # This normalizes all the options
|
35
|
-
end
|
35
|
+
def initialize(view = nil, attributes = {})
|
36
|
+
(attributes = view; view = nil) if view.kind_of?(Hash)
|
36
37
|
|
37
|
-
|
38
|
-
|
39
|
-
initialize_chart_options
|
40
|
-
end
|
38
|
+
@attributes = initial_attributes(attributes)
|
39
|
+
@state = initial_state
|
41
40
|
|
42
|
-
|
43
|
-
|
44
|
-
|
41
|
+
@_aggregates = {}
|
42
|
+
@_bulk_actions = []
|
43
|
+
@_charts = {}
|
44
|
+
@_columns = {}
|
45
|
+
@_filters = {}
|
46
|
+
@_form = {}
|
47
|
+
@_scopes = {}
|
45
48
|
|
46
|
-
|
47
|
-
|
48
|
-
end
|
49
|
+
raise 'collection is defined as a method. Please use the collection do ... end syntax.' unless collection.nil?
|
50
|
+
self.view = view if view
|
49
51
|
end
|
50
52
|
|
51
|
-
|
52
|
-
|
53
|
-
|
53
|
+
# Once the view is assigned, we initialize everything
|
54
|
+
def view=(view)
|
55
|
+
@view = (view.respond_to?(:view_context) ? view.view_context : view)
|
56
|
+
raise 'expected view to respond to params' unless @view.respond_to?(:params)
|
54
57
|
|
55
|
-
|
56
|
-
|
57
|
-
end
|
58
|
+
load_cookie!
|
59
|
+
load_attributes!
|
58
60
|
|
59
|
-
|
60
|
-
|
61
|
-
|
61
|
+
# We need early access to filter and scope, to define defaults from the model first
|
62
|
+
# This means filters do knows about attributes but not about columns.
|
63
|
+
initialize_filters if respond_to?(:initialize_filters)
|
64
|
+
load_filters!
|
65
|
+
load_state!
|
62
66
|
|
63
|
-
|
64
|
-
|
65
|
-
|
67
|
+
# Now we initialize all the columns. columns knows about attributes and filters and scope
|
68
|
+
initialize_datatable if respond_to?(:initialize_datatable)
|
69
|
+
load_columns!
|
66
70
|
|
67
|
-
|
68
|
-
|
69
|
-
|
71
|
+
# Execute any additional DSL methods
|
72
|
+
initialize_bulk_actions if respond_to?(:initialize_bulk_actions)
|
73
|
+
initialize_charts if respond_to?(:initialize_charts)
|
70
74
|
|
71
|
-
|
72
|
-
|
73
|
-
|
75
|
+
# Load the collection. This is the first time def collection is called on the Datatable itself
|
76
|
+
initialize_collection if respond_to?(:initialize_collection)
|
77
|
+
load_collection!
|
74
78
|
|
75
|
-
|
76
|
-
|
77
|
-
end
|
79
|
+
# Figure out the class, and if it's activerecord, do all the resource discovery on it
|
80
|
+
load_resource!
|
78
81
|
|
79
|
-
|
80
|
-
def attributes
|
81
|
-
@attributes ||= HashWithIndifferentAccess.new
|
82
|
+
save_cookie!
|
82
83
|
end
|
83
84
|
|
84
|
-
def
|
85
|
+
def present?(view = nil)
|
86
|
+
unless (@view || view)
|
87
|
+
raise 'unable to call present? without an assigned view. In your view, either call render_datatable(@datatable) first, or use @datatable.present?(self)'
|
88
|
+
end
|
85
89
|
|
86
|
-
|
87
|
-
def model_name # Searching & Filters
|
88
|
-
@model_name ||= ActiveModel::Name.new(self.class)
|
89
|
-
end
|
90
|
+
self.view ||= view
|
90
91
|
|
91
|
-
|
92
|
-
@model_name ||= ActiveModel::Name.new(self)
|
92
|
+
to_json[:recordsTotal] > 0
|
93
93
|
end
|
94
94
|
|
95
|
-
def
|
96
|
-
@
|
97
|
-
|
95
|
+
def blank?(view = nil)
|
96
|
+
unless (@view || view)
|
97
|
+
raise 'unable to call blank? without an assigned view. In your view, either call render_datatable(@datatable) first, or use @datatable.blank?(self)'
|
98
|
+
end
|
98
99
|
|
99
|
-
|
100
|
-
raise "You must define a collection. Something like an ActiveRecord User.all or an Array of Arrays [[1, 'something'], [2, 'something else']]"
|
101
|
-
end
|
100
|
+
self.view ||= view
|
102
101
|
|
103
|
-
|
104
|
-
@collection_class # Will be either User/Post/etc or Array
|
102
|
+
to_json[:recordsTotal] == 0
|
105
103
|
end
|
106
104
|
|
107
105
|
def to_json
|
108
|
-
|
109
|
-
|
110
|
-
@json ||= begin
|
111
|
-
data = table_data
|
112
|
-
|
106
|
+
@json ||= (
|
113
107
|
{
|
108
|
+
data: (compute || []),
|
114
109
|
draw: (params[:draw] || 0),
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
charts: (charts_data || {})
|
110
|
+
recordsTotal: (@total_records || 0),
|
111
|
+
recordsFiltered: (@display_records || 0),
|
112
|
+
aggregates: (@aggregates_data || []),
|
113
|
+
charts: (@charts_data || {})
|
120
114
|
}
|
121
|
-
|
122
|
-
end
|
123
|
-
|
124
|
-
def present?
|
125
|
-
total_records > 0 || current_scope.present?
|
126
|
-
end
|
127
|
-
|
128
|
-
def empty?
|
129
|
-
total_records == 0 && current_scope.blank?
|
130
|
-
end
|
131
|
-
|
132
|
-
def total_records
|
133
|
-
@total_records ||= (active_record_collection? ? active_record_collection_size(the_collection) : the_collection.size)
|
134
|
-
end
|
135
|
-
|
136
|
-
def view=(view_context)
|
137
|
-
@view = view_context
|
138
|
-
@view.formats = [:html]
|
139
|
-
|
140
|
-
# 'Just work' with attributes
|
141
|
-
@view.class.send(:attr_accessor, :attributes)
|
142
|
-
@view.attributes = self.attributes
|
143
|
-
|
144
|
-
# Delegate any methods defined on the datatable directly to our view
|
145
|
-
@view.class.send(:attr_accessor, :effective_datatable)
|
146
|
-
@view.effective_datatable = self
|
147
|
-
|
148
|
-
unless @view.respond_to?(:bulk_action)
|
149
|
-
@view.class.send(:include, Effective::EffectiveDatatable::Dsl::BulkActions)
|
150
|
-
end
|
151
|
-
|
152
|
-
Effective::EffectiveDatatable::Helpers.instance_methods(false).each do |helper_method|
|
153
|
-
@view.class_eval { delegate helper_method, to: :@effective_datatable }
|
154
|
-
end
|
155
|
-
|
156
|
-
(self.class.instance_methods(false) - [:initialize_datatable, :collection, :search_column, :order_column]).each do |view_method|
|
157
|
-
@view.class_eval { delegate view_method, to: :@effective_datatable }
|
158
|
-
end
|
159
|
-
|
160
|
-
# Clear the search_terms memoization
|
161
|
-
@search_terms = nil
|
162
|
-
@order_name = nil
|
163
|
-
@order_direction = nil
|
164
|
-
end
|
165
|
-
|
166
|
-
def view_context
|
167
|
-
view
|
168
|
-
end
|
169
|
-
|
170
|
-
def table_html_class
|
171
|
-
@table_html_class.presence || 'table table-bordered table-striped'
|
115
|
+
)
|
172
116
|
end
|
173
117
|
|
174
118
|
# When simple only a table will be rendered with
|
175
119
|
# no sorting, no filtering, no export buttons, no pagination, no per page, no colReorder
|
176
120
|
# default sorting only, default visibility only, all records returned, and responsive enabled
|
177
121
|
def simple?
|
178
|
-
|
122
|
+
attributes[:simple] == true
|
179
123
|
end
|
180
124
|
|
181
|
-
|
125
|
+
# Whether the filters must be rendered as a <form> or we can keep the normal <div> behaviour
|
126
|
+
def _filters_form_required?
|
127
|
+
_form[:verb].present?
|
128
|
+
end
|
182
129
|
|
183
|
-
def
|
184
|
-
|
130
|
+
def table_html_class
|
131
|
+
attributes[:class] || 'table table-bordered table-striped'
|
185
132
|
end
|
186
133
|
|
187
|
-
def
|
188
|
-
|
134
|
+
def to_param
|
135
|
+
@to_param ||= self.class.name.underscore.parameterize
|
189
136
|
end
|
190
137
|
|
191
|
-
def
|
192
|
-
@
|
138
|
+
def columns
|
139
|
+
@_columns
|
193
140
|
end
|
194
141
|
|
195
|
-
def
|
196
|
-
@
|
142
|
+
def collection
|
143
|
+
@_collection
|
197
144
|
end
|
198
145
|
|
199
|
-
|
200
|
-
|
201
|
-
# Usually that will make the table results look weird.
|
202
|
-
def active_record_collection?
|
203
|
-
@active_record_collection == true
|
146
|
+
def dsl_tool
|
147
|
+
@dsl_tool ||= DatatableDslTool.new(self)
|
204
148
|
end
|
205
149
|
|
206
|
-
|
207
|
-
|
150
|
+
private
|
151
|
+
|
152
|
+
def column_tool
|
153
|
+
@column_tool ||= DatatableColumnTool.new(self)
|
208
154
|
end
|
209
155
|
|
210
|
-
|
211
|
-
|
212
|
-
# User.select(:email, :first_name).count will throw an error
|
213
|
-
# .count(:all) and .size seem to work
|
214
|
-
# Grouped Queries:
|
215
|
-
# User.all.group(:email).count will return a Hash
|
216
|
-
def active_record_collection_size(collection)
|
217
|
-
count = (collection.size rescue nil)
|
218
|
-
|
219
|
-
case count
|
220
|
-
when Integer
|
221
|
-
count
|
222
|
-
when Hash
|
223
|
-
count.size # This represents the number of displayed datatable rows, not the sum all groups (which might be more)
|
224
|
-
else
|
225
|
-
if collection.klass.connection.respond_to?(:unprepared_statement)
|
226
|
-
collection_sql = collection.klass.connection.unprepared_statement { collection.to_sql }
|
227
|
-
(collection.klass.connection.exec_query("SELECT COUNT(*) FROM (#{collection_sql}) AS datatables_total_count").rows[0][0] rescue 1)
|
228
|
-
else
|
229
|
-
(collection.klass.connection.exec_query("SELECT COUNT(*) FROM (#{collection.to_sql}) AS datatables_total_count").rows[0][0] rescue 1)
|
230
|
-
end.to_i
|
231
|
-
end
|
156
|
+
def value_tool
|
157
|
+
@value_tool ||= DatatableValueTool.new(self)
|
232
158
|
end
|
233
159
|
|
234
160
|
end
|