effective_datatables 2.12.2 → 3.0.0
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/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
|