ajax-datatables-rails 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.codeclimate.yml +26 -0
- data/.gitignore +20 -0
- data/.rspec +1 -0
- data/.rubocop.yml +1157 -0
- data/.travis.yml +68 -0
- data/Appraisals +34 -0
- data/Gemfile +5 -1
- data/LICENSE +17 -18
- data/README.md +239 -239
- data/Rakefile +1 -1
- data/ajax-datatables-rails.gemspec +31 -24
- data/gemfiles/rails_4.0.13.gemfile +14 -0
- data/gemfiles/rails_4.1.15.gemfile +14 -0
- data/gemfiles/rails_4.2.8.gemfile +13 -0
- data/gemfiles/rails_5.0.3.gemfile +13 -0
- data/gemfiles/rails_5.1.1.gemfile +13 -0
- data/lib/ajax-datatables-rails.rb +9 -8
- data/lib/ajax-datatables-rails/base.rb +80 -156
- data/lib/ajax-datatables-rails/config.rb +8 -5
- data/lib/ajax-datatables-rails/datatable/column.rb +169 -0
- data/lib/ajax-datatables-rails/datatable/column_date_filter.rb +41 -0
- data/lib/ajax-datatables-rails/datatable/datatable.rb +79 -0
- data/lib/ajax-datatables-rails/datatable/simple_order.rb +31 -0
- data/lib/ajax-datatables-rails/datatable/simple_search.rb +18 -0
- data/lib/ajax-datatables-rails/orm/active_record.rb +52 -0
- data/lib/ajax-datatables-rails/version.rb +1 -1
- data/lib/generators/datatable/templates/ajax_datatables_rails_config.rb +3 -3
- data/lib/generators/rails/datatable_generator.rb +7 -19
- data/lib/generators/rails/templates/datatable.rb +26 -14
- data/spec/ajax-datatables-rails/base_spec.rb +190 -0
- data/spec/ajax-datatables-rails/configuration_spec.rb +43 -0
- data/spec/ajax-datatables-rails/datatable/column_spec.rb +109 -0
- data/spec/ajax-datatables-rails/datatable/datatable_spec.rb +87 -0
- data/spec/ajax-datatables-rails/datatable/simple_order_spec.rb +13 -0
- data/spec/ajax-datatables-rails/datatable/simple_search_spec.rb +17 -0
- data/spec/ajax-datatables-rails/extended_spec.rb +20 -0
- data/spec/ajax-datatables-rails/orm/active_record_filter_records_spec.rb +439 -0
- data/spec/ajax-datatables-rails/orm/active_record_paginate_records_spec.rb +66 -0
- data/spec/ajax-datatables-rails/orm/active_record_sort_records_spec.rb +34 -0
- data/spec/ajax-datatables-rails/orm/active_record_spec.rb +25 -0
- data/spec/factories/user.rb +9 -0
- data/spec/install_oracle.sh +12 -0
- data/spec/spec_helper.rb +75 -3
- data/spec/support/schema.rb +14 -0
- data/spec/support/test_helpers.rb +174 -0
- data/spec/support/test_models.rb +2 -0
- metadata +169 -37
- data/lib/ajax-datatables-rails/extensions/kaminari.rb +0 -12
- data/lib/ajax-datatables-rails/extensions/simple_paginator.rb +0 -12
- data/lib/ajax-datatables-rails/extensions/will_paginate.rb +0 -12
- data/lib/ajax-datatables-rails/models.rb +0 -6
- data/spec/ajax-datatables-rails/ajax_datatables_rails_spec.rb +0 -351
- data/spec/ajax-datatables-rails/kaminari_spec.rb +0 -35
- data/spec/ajax-datatables-rails/models_spec.rb +0 -10
- data/spec/ajax-datatables-rails/simple_paginator_spec.rb +0 -32
- data/spec/ajax-datatables-rails/will_paginate_spec.rb +0 -28
- data/spec/schema.rb +0 -35
- data/spec/test_models.rb +0 -21
data/Rakefile
CHANGED
@@ -1,30 +1,37 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
1
|
+
# coding: utf-8
|
2
|
+
$:.push File.expand_path('../lib', __FILE__)
|
4
3
|
require 'ajax-datatables-rails/version'
|
5
4
|
|
6
|
-
Gem::Specification.new do |
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'ajax-datatables-rails'
|
7
|
+
s.version = AjaxDatatablesRails::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ['Joel Quenneville', 'Antonio Antillon']
|
10
|
+
s.email = ['joel.quenneville@collegeplus.org', 'antillas21@gmail.com']
|
11
|
+
s.homepage = 'https://github.com/jbox-web/ajax-datatables-rails'
|
12
|
+
s.summary = %q{A gem that simplifies using datatables and hundreds of records via ajax}
|
13
|
+
s.description = %q{A wrapper around datatable's ajax methods that allow synchronization with server-side pagination in a rails app}
|
14
|
+
s.license = 'MIT'
|
15
15
|
|
16
|
-
|
17
|
-
gem.executables = gem.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
-
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
|
-
gem.require_path = "lib"
|
16
|
+
s.add_dependency 'railties', '>= 4.0'
|
20
17
|
|
21
|
-
|
18
|
+
s.add_development_dependency 'rails', '>= 4.0'
|
19
|
+
s.add_development_dependency 'rake'
|
20
|
+
s.add_development_dependency 'pg'
|
21
|
+
s.add_development_dependency 'mysql2'
|
22
|
+
s.add_development_dependency 'sqlite3'
|
23
|
+
s.add_development_dependency 'activerecord-oracle_enhanced-adapter'
|
24
|
+
s.add_development_dependency 'rspec'
|
25
|
+
s.add_development_dependency 'generator_spec'
|
26
|
+
s.add_development_dependency 'pry'
|
27
|
+
s.add_development_dependency 'simplecov'
|
28
|
+
s.add_development_dependency 'database_cleaner'
|
29
|
+
s.add_development_dependency 'factory_girl'
|
30
|
+
s.add_development_dependency 'faker'
|
31
|
+
s.add_development_dependency 'appraisal'
|
22
32
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
gem.add_development_dependency "sqlite3"
|
28
|
-
gem.add_development_dependency "rails", ">= 3.1.0"
|
29
|
-
gem.add_development_dependency "activerecord", ">= 4.1.6"
|
33
|
+
s.files = `git ls-files`.split("\n")
|
34
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
35
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
36
|
+
s.require_paths = ['lib']
|
30
37
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gem "rails", "4.0.13"
|
6
|
+
gem "mysql2", "~> 0.3.18"
|
7
|
+
gem "activerecord-oracle_enhanced-adapter", "~> 1.5.0"
|
8
|
+
gem "ruby-oci8" if ENV["DB_ADAPTER"] == "oracle_enhanced"
|
9
|
+
|
10
|
+
group :test do
|
11
|
+
gem "codeclimate-test-reporter", "~> 1.0.0"
|
12
|
+
end
|
13
|
+
|
14
|
+
gemspec path: "../"
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gem "rails", "4.1.15"
|
6
|
+
gem "mysql2", "~> 0.3.18"
|
7
|
+
gem "activerecord-oracle_enhanced-adapter", "~> 1.5.0"
|
8
|
+
gem "ruby-oci8" if ENV["DB_ADAPTER"] == "oracle_enhanced"
|
9
|
+
|
10
|
+
group :test do
|
11
|
+
gem "codeclimate-test-reporter", "~> 1.0.0"
|
12
|
+
end
|
13
|
+
|
14
|
+
gemspec path: "../"
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gem "rails", "4.2.8"
|
6
|
+
gem "activerecord-oracle_enhanced-adapter", "~> 1.6.0"
|
7
|
+
gem "ruby-oci8" if ENV["DB_ADAPTER"] == "oracle_enhanced"
|
8
|
+
|
9
|
+
group :test do
|
10
|
+
gem "codeclimate-test-reporter", "~> 1.0.0"
|
11
|
+
end
|
12
|
+
|
13
|
+
gemspec path: "../"
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gem "rails", "5.0.3"
|
6
|
+
gem "activerecord-oracle_enhanced-adapter", "~> 1.7.0"
|
7
|
+
gem "ruby-oci8" if ENV["DB_ADAPTER"] == "oracle_enhanced"
|
8
|
+
|
9
|
+
group :test do
|
10
|
+
gem "codeclimate-test-reporter", "~> 1.0.0"
|
11
|
+
end
|
12
|
+
|
13
|
+
gemspec path: "../"
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gem "rails", "5.1.1"
|
6
|
+
gem "activerecord-oracle_enhanced-adapter", "~> 1.8.0"
|
7
|
+
gem "ruby-oci8" if ENV["DB_ADAPTER"] == "oracle_enhanced"
|
8
|
+
|
9
|
+
group :test do
|
10
|
+
gem "codeclimate-test-reporter", "~> 1.0.0"
|
11
|
+
end
|
12
|
+
|
13
|
+
gemspec path: "../"
|
@@ -1,10 +1,11 @@
|
|
1
|
-
require 'ajax-datatables-rails/version'
|
2
|
-
require 'ajax-datatables-rails/config'
|
3
|
-
require 'ajax-datatables-rails/models'
|
4
|
-
require 'ajax-datatables-rails/base'
|
5
|
-
require 'ajax-datatables-rails/extensions/simple_paginator'
|
6
|
-
require 'ajax-datatables-rails/extensions/kaminari'
|
7
|
-
require 'ajax-datatables-rails/extensions/will_paginate'
|
8
|
-
|
9
1
|
module AjaxDatatablesRails
|
2
|
+
require 'ajax-datatables-rails/version'
|
3
|
+
require 'ajax-datatables-rails/config'
|
4
|
+
require 'ajax-datatables-rails/base'
|
5
|
+
require 'ajax-datatables-rails/datatable/datatable'
|
6
|
+
require 'ajax-datatables-rails/datatable/simple_search'
|
7
|
+
require 'ajax-datatables-rails/datatable/simple_order'
|
8
|
+
require 'ajax-datatables-rails/datatable/column_date_filter' unless AjaxDatatablesRails.old_rails?
|
9
|
+
require 'ajax-datatables-rails/datatable/column'
|
10
|
+
require 'ajax-datatables-rails/orm/active_record'
|
10
11
|
end
|
@@ -1,214 +1,138 @@
|
|
1
1
|
module AjaxDatatablesRails
|
2
|
+
class NotImplemented < StandardError; end
|
3
|
+
|
2
4
|
class Base
|
3
5
|
extend Forwardable
|
4
|
-
class MethodNotImplementedError < StandardError; end
|
5
6
|
|
6
|
-
attr_reader :view, :options
|
7
|
-
def_delegator :@view, :params
|
7
|
+
attr_reader :view, :options
|
8
|
+
def_delegator :@view, :params
|
8
9
|
|
9
10
|
def initialize(view, options = {})
|
10
|
-
@view
|
11
|
+
@view = view
|
11
12
|
@options = options
|
12
|
-
|
13
|
+
load_orm_extension
|
13
14
|
end
|
14
15
|
|
15
16
|
def config
|
16
17
|
@config ||= AjaxDatatablesRails.config
|
17
18
|
end
|
18
19
|
|
19
|
-
def
|
20
|
-
@
|
21
|
-
end
|
22
|
-
|
23
|
-
def searchable_columns
|
24
|
-
@searchable_columns ||= []
|
20
|
+
def datatable
|
21
|
+
@datatable ||= Datatable::Datatable.new(self)
|
25
22
|
end
|
26
23
|
|
27
|
-
def
|
28
|
-
fail(
|
29
|
-
MethodNotImplementedError,
|
30
|
-
'Please implement this method in your class.'
|
31
|
-
)
|
24
|
+
def view_columns
|
25
|
+
fail(NotImplemented, view_columns_error_text)
|
32
26
|
end
|
33
27
|
|
34
28
|
def get_raw_records
|
35
|
-
fail(
|
36
|
-
MethodNotImplementedError,
|
37
|
-
'Please implement this method in your class.'
|
38
|
-
)
|
29
|
+
fail(NotImplemented, raw_records_error_text)
|
39
30
|
end
|
40
31
|
|
41
|
-
def
|
42
|
-
|
43
|
-
:draw => params[:draw].to_i,
|
44
|
-
:recordsTotal => get_raw_records.count(:all),
|
45
|
-
:recordsFiltered => filter_records(get_raw_records).count(:all),
|
46
|
-
:data => data
|
47
|
-
}
|
32
|
+
def data
|
33
|
+
fail(NotImplemented, data_error_text)
|
48
34
|
end
|
49
35
|
|
50
|
-
def
|
51
|
-
|
52
|
-
|
53
|
-
if(respond_to?(:logger) && logger.present?)
|
54
|
-
logger.warn(warning)
|
55
|
-
else
|
56
|
-
warn(warning)
|
57
|
-
end
|
36
|
+
def additional_datas
|
37
|
+
{}
|
58
38
|
end
|
59
39
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
40
|
+
def as_json(*)
|
41
|
+
{
|
42
|
+
recordsTotal: records_total_count,
|
43
|
+
recordsFiltered: records_filtered_count,
|
44
|
+
data: sanitize(data)
|
45
|
+
}.merge(additional_datas)
|
64
46
|
end
|
65
47
|
|
66
|
-
def
|
67
|
-
records
|
68
|
-
records = sort_records(records) if params[:order].present?
|
69
|
-
records = filter_records(records) if params[:search].present?
|
70
|
-
records = paginate_records(records) unless params[:length].present? && params[:length] == '-1'
|
71
|
-
records
|
48
|
+
def records
|
49
|
+
@records ||= retrieve_records
|
72
50
|
end
|
73
51
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
52
|
+
# helper methods
|
53
|
+
def connected_columns
|
54
|
+
@connected_columns ||= begin
|
55
|
+
view_columns.keys.map do |field_name|
|
56
|
+
datatable.column_by(:data, field_name.to_s)
|
57
|
+
end.compact
|
78
58
|
end
|
79
|
-
records.order(sort_by.join(", "))
|
80
|
-
end
|
81
|
-
|
82
|
-
def paginate_records(records)
|
83
|
-
fail(
|
84
|
-
MethodNotImplementedError,
|
85
|
-
'Please mixin a pagination extension.'
|
86
|
-
)
|
87
|
-
end
|
88
|
-
|
89
|
-
def filter_records(records)
|
90
|
-
records = simple_search(records)
|
91
|
-
records = composite_search(records)
|
92
|
-
records
|
93
|
-
end
|
94
|
-
|
95
|
-
def simple_search(records)
|
96
|
-
return records unless (params[:search].present? && params[:search][:value].present?)
|
97
|
-
conditions = build_conditions_for(params[:search][:value])
|
98
|
-
records = records.where(conditions) if conditions
|
99
|
-
records
|
100
59
|
end
|
101
60
|
|
102
|
-
def
|
103
|
-
|
104
|
-
|
105
|
-
records
|
106
|
-
end
|
107
|
-
|
108
|
-
def build_conditions_for(query)
|
109
|
-
search_for = query.split(' ')
|
110
|
-
criteria = search_for.inject([]) do |criteria, atom|
|
111
|
-
criteria << searchable_columns.map { |col| search_condition(col, atom) }.reduce(:or)
|
112
|
-
end.reduce(:and)
|
113
|
-
criteria
|
114
|
-
end
|
115
|
-
|
116
|
-
def search_condition(column, value)
|
117
|
-
if column[0] == column.downcase[0]
|
118
|
-
::AjaxDatatablesRails::Base.deprecated '[DEPRECATED] Using table_name.column_name notation is deprecated. Please refer to: https://github.com/antillas21/ajax-datatables-rails#searchable-and-sortable-columns-syntax'
|
119
|
-
return deprecated_search_condition(column, value)
|
120
|
-
else
|
121
|
-
return new_search_condition(column, value)
|
61
|
+
def searchable_columns
|
62
|
+
@searchable_columns ||= begin
|
63
|
+
connected_columns.select(&:searchable?)
|
122
64
|
end
|
123
65
|
end
|
124
66
|
|
125
|
-
def
|
126
|
-
|
127
|
-
|
128
|
-
casted_column = ::Arel::Nodes::NamedFunction.new('CAST', [model.arel_table[column.to_sym].as(typecast)])
|
129
|
-
casted_column.matches("%#{value}%")
|
130
|
-
end
|
131
|
-
|
132
|
-
def deprecated_search_condition(column, value)
|
133
|
-
model, column = column.split('.')
|
134
|
-
model = model.singularize.titleize.gsub( / /, '' ).constantize
|
135
|
-
|
136
|
-
casted_column = ::Arel::Nodes::NamedFunction.new('CAST', [model.arel_table[column.to_sym].as(typecast)])
|
137
|
-
casted_column.matches("%#{value}%")
|
138
|
-
end
|
139
|
-
|
140
|
-
def aggregate_query
|
141
|
-
conditions = searchable_columns.each_with_index.map do |column, index|
|
142
|
-
value = params[:columns]["#{index}"][:search][:value] if params[:columns]
|
143
|
-
search_condition(column, value) unless value.blank?
|
67
|
+
def search_columns
|
68
|
+
@search_columns ||= begin
|
69
|
+
searchable_columns.select(&:searched?)
|
144
70
|
end
|
145
|
-
conditions.compact.reduce(:and)
|
146
71
|
end
|
147
72
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
73
|
+
private
|
74
|
+
|
75
|
+
def sanitize(data)
|
76
|
+
data.map do |record|
|
77
|
+
if record.is_a?(Array)
|
78
|
+
record.map { |td| ERB::Util.html_escape(td) }
|
79
|
+
else
|
80
|
+
record.update(record){ |_, v| ERB::Util.html_escape(v) }
|
81
|
+
end
|
154
82
|
end
|
155
83
|
end
|
156
84
|
|
157
|
-
def
|
158
|
-
|
85
|
+
def retrieve_records
|
86
|
+
records = fetch_records
|
87
|
+
records = filter_records(records)
|
88
|
+
records = sort_records(records) if datatable.orderable?
|
89
|
+
records = paginate_records(records) if datatable.paginate?
|
90
|
+
records
|
159
91
|
end
|
160
92
|
|
161
|
-
def
|
162
|
-
(
|
93
|
+
def records_total_count
|
94
|
+
get_raw_records.count(:all)
|
163
95
|
end
|
164
96
|
|
165
|
-
def
|
166
|
-
|
97
|
+
def records_filtered_count
|
98
|
+
filter_records(get_raw_records).count(:all)
|
167
99
|
end
|
168
100
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
101
|
+
# Private helper methods
|
102
|
+
def load_orm_extension
|
103
|
+
case config.orm
|
104
|
+
when :mongoid then nil
|
105
|
+
when :active_record then extend ORM::ActiveRecord
|
106
|
+
else
|
107
|
+
nil
|
108
|
+
end
|
174
109
|
end
|
175
110
|
|
176
|
-
def
|
177
|
-
|
178
|
-
end
|
111
|
+
def raw_records_error_text
|
112
|
+
return <<-eos
|
179
113
|
|
180
|
-
|
181
|
-
|
182
|
-
|
114
|
+
You should implement this method in your class and specify
|
115
|
+
how records are going to be retrieved from the database.
|
116
|
+
eos
|
183
117
|
end
|
184
118
|
|
185
|
-
def
|
186
|
-
|
187
|
-
options.include?(item[:dir]) ? item[:dir].upcase : 'ASC'
|
188
|
-
end
|
119
|
+
def data_error_text
|
120
|
+
return <<-eos
|
189
121
|
|
190
|
-
|
191
|
-
|
122
|
+
You should implement this method in your class and return an array
|
123
|
+
of arrays, or an array of hashes, as defined in the jQuery.dataTables
|
124
|
+
plugin documentation.
|
125
|
+
eos
|
192
126
|
end
|
193
127
|
|
194
|
-
def
|
195
|
-
|
196
|
-
params[:columns].each_value do |column|
|
197
|
-
@sortable_displayed_columns << column[:data] if column[:orderable] == 'true'
|
198
|
-
end
|
199
|
-
@sortable_displayed_columns
|
200
|
-
end
|
128
|
+
def view_columns_error_text
|
129
|
+
return <<-eos
|
201
130
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
extend Extensions::WillPaginate
|
208
|
-
else
|
209
|
-
extend Extensions::SimplePaginator
|
210
|
-
end
|
211
|
-
self
|
131
|
+
You should implement this method in your class and return an array
|
132
|
+
of database columns based on the columns displayed in the HTML view.
|
133
|
+
These columns should be represented in the ModelName.column_name,
|
134
|
+
or aliased_join_table.column_name notation.
|
135
|
+
eos
|
212
136
|
end
|
213
137
|
end
|
214
138
|
end
|