datatables 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/MIT-LICENSE +21 -0
- data/README.rdoc +134 -0
- data/Rakefile +2 -0
- data/app/controllers/datatables_controller.rb +19 -0
- data/app/views/datatable/_datatable.html.erb +163 -0
- data/config/routes.rb +5 -0
- data/datatables.gemspec +25 -0
- data/lib/datatables.rb +5 -0
- data/lib/datatables/activerecord_methods.rb +130 -0
- data/lib/datatables/datatable_helpers.rb +31 -0
- data/lib/datatables/engine.rb +9 -0
- data/lib/generators/datatables/install/install_generator.rb +21 -0
- data/vendor/assets/javascripts/jquery.dataTables.min.js +142 -0
- data/vendor/assets/stylesheets/datatable_page.css +93 -0
- data/vendor/assets/stylesheets/datatable_table.css +538 -0
- metadata +94 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2004-2011 Caseproof, LLC
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
data/README.rdoc
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
= Datatables
|
2
|
+
|
3
|
+
Datatables is a Rails 3 plugin that enables the easy creation of dynamic datatable views on top of any ActiveRecord model. Datatables provides a simple helper that can be utilized in the view to automatically display a dynamic view on top of a model. Datatables handles the entire front end and backend support to do this.
|
4
|
+
|
5
|
+
= Installation
|
6
|
+
|
7
|
+
To install datatables to your rails project, follow these simple steps:
|
8
|
+
|
9
|
+
==== 1. Make sure your project is using the 'jquery-rails' plugin.
|
10
|
+
==== 2. Add the following line to your Gemfile:
|
11
|
+
gem 'datatables', :git => 'git://github.com/Caseproof/datatables.git'
|
12
|
+
==== 3. Run <b>bundle install</b>
|
13
|
+
==== 4. Run <b>rails generate datatables:install</b>
|
14
|
+
==== 5. Add the following lines to your layout file after <b>javascript_include_tag :defaults</b>
|
15
|
+
<%= stylesheet_link_tag "datatable_page" %>
|
16
|
+
<%= stylesheet_link_tag "datatable_table" %>
|
17
|
+
<%= javascript_include_tag 'jquery.dataTables.min' %>
|
18
|
+
==== 6. Add the Datatable helper mixin to your ApplicationHelper (<b>app/helpers/application_helper.rb</b>) like so:
|
19
|
+
module ApplicationHelper
|
20
|
+
include Datatables::Helpers
|
21
|
+
end
|
22
|
+
|
23
|
+
= Example
|
24
|
+
|
25
|
+
With datatables it's easy to add rich datatables to your views that correspond with your active record models.
|
26
|
+
|
27
|
+
There is a lovely helper that you can use to render your datatable that takes in a whole host of options. Unfortunately, there's still quite a bit of work to do with these options to handle every scenario but here's what it support so far:
|
28
|
+
|
29
|
+
== Database table:
|
30
|
+
|
31
|
+
The following examples will use the following database table:
|
32
|
+
|
33
|
+
mysql> desc companies;
|
34
|
+
+-------------+--------------+------+-----+---------+----------------+
|
35
|
+
| Field | Type | Null | Key | Default | Extra |
|
36
|
+
+-------------+--------------+------+-----+---------+----------------+
|
37
|
+
| id | int(11) | NO | PRI | NULL | auto_increment |
|
38
|
+
| name | varchar(255) | YES | MUL | NULL | |
|
39
|
+
| slug | varchar(255) | YES | MUL | NULL | |
|
40
|
+
| domain | varchar(255) | YES | MUL | NULL | |
|
41
|
+
| category_id | int(11) | NO | MUL | NULL | |
|
42
|
+
| created_at | datetime | YES | | NULL | |
|
43
|
+
| updated_at | datetime | YES | | NULL | |
|
44
|
+
+-------------+--------------+------+-----+---------+----------------+
|
45
|
+
|
46
|
+
|
47
|
+
== Standard datatable
|
48
|
+
|
49
|
+
The first argument to the datatable helper is the name of the model or an array of model & scope. The second argument is a hash of column names & options.
|
50
|
+
|
51
|
+
<%= datatable('company', { :name => { :type => 'string',
|
52
|
+
:label => 'Name',
|
53
|
+
:width => '20%' },
|
54
|
+
:slug => { :type => 'string',
|
55
|
+
:label => 'Slug',
|
56
|
+
:width => '15%' },
|
57
|
+
:domain => { :type => 'string',
|
58
|
+
:label => 'Domain',
|
59
|
+
:width => '15%' }
|
60
|
+
}) %>
|
61
|
+
|
62
|
+
== Datatable with a link to edit
|
63
|
+
|
64
|
+
Note that the edit link path utilizes the :id field in the database table to automatically insert the correct id on a row by row basis:
|
65
|
+
|
66
|
+
<%= datatable('company', { :id => { :type => 'hidden' },
|
67
|
+
:name => { :type => 'link',
|
68
|
+
:label => 'Name',
|
69
|
+
:link => edit_admin_company_path(:id),
|
70
|
+
:replace => 'id',
|
71
|
+
:width => '50%' },
|
72
|
+
:slug => { :type => 'string',
|
73
|
+
:label => 'Slug',
|
74
|
+
:width => '25%' },
|
75
|
+
:domain => { :type => 'string',
|
76
|
+
:label => 'Domain',
|
77
|
+
:width => '25%' }
|
78
|
+
}) %>
|
79
|
+
|
80
|
+
== Scoped datatable (now we're using the 'dot_org_domains' that can be found in the Company model):
|
81
|
+
|
82
|
+
<%= datatable(['company','dot_org_domains'], { :id => { :type => 'hidden' },
|
83
|
+
:name => { :type => 'link',
|
84
|
+
:label => 'Name',
|
85
|
+
:link => edit_admin_company_path(:id),
|
86
|
+
:replace => 'id',
|
87
|
+
:width => '50%' },
|
88
|
+
:slug => { :type => 'string',
|
89
|
+
:label => 'Slug',
|
90
|
+
:width => '25%' },
|
91
|
+
:domain => { :type => 'string',
|
92
|
+
:label => 'Domain',
|
93
|
+
:width => '25%' }
|
94
|
+
}) %>
|
95
|
+
|
96
|
+
== Association columns
|
97
|
+
<%= datatable(['company','dot_org_domains'], { :id => { :type => 'hidden' },
|
98
|
+
:name => { :type => 'link',
|
99
|
+
:label => 'Name',
|
100
|
+
:link => edit_admin_company_path(:id),
|
101
|
+
:replace => 'id',
|
102
|
+
:width => '40%' },
|
103
|
+
:slug => { :type => 'string',
|
104
|
+
:label => 'Slug',
|
105
|
+
:width => '20%' },
|
106
|
+
:domain => { :type => 'string',
|
107
|
+
:label => 'Domain',
|
108
|
+
:width => '20%' },
|
109
|
+
:category_name => { :type => 'string',
|
110
|
+
:label => 'Category',
|
111
|
+
:column => 'categories.name',
|
112
|
+
:width => '20%',
|
113
|
+
:class => 'center' }
|
114
|
+
|
115
|
+
}) %>
|
116
|
+
|
117
|
+
= Why use this plugin?
|
118
|
+
|
119
|
+
It is the easiest way to integrate dynamic datatables using the jQuery datatables plugin into your rails app.
|
120
|
+
|
121
|
+
= Version history
|
122
|
+
|
123
|
+
- Version 1.0.0
|
124
|
+
- First Release
|
125
|
+
|
126
|
+
= Contribute
|
127
|
+
|
128
|
+
If you've got some ideas for datatables let me know and, even better, if you've made some enhancements to the code send me a pull request!
|
129
|
+
|
130
|
+
= Support
|
131
|
+
|
132
|
+
Bug report? Faulty/incomplete documentation? Feature request? Please post an issue on 'http://github.com/Caseproof/metafy/issues'. If its urgent, please contact me from my website at 'http://blairwilliams.com/contact'
|
133
|
+
|
134
|
+
Copyright (c) 2004-2011 Caseproof, LLC, released under the MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
class DatatablesController < ApplicationController
|
2
|
+
#before_filter :authenticate_user!
|
3
|
+
#load_and_authorize_resource
|
4
|
+
respond_to :json
|
5
|
+
|
6
|
+
def dataset
|
7
|
+
begin
|
8
|
+
model_class = params[:model].classify.constantize
|
9
|
+
rescue NameError
|
10
|
+
render :text => 'Model Not Found', :layout => false
|
11
|
+
return
|
12
|
+
end
|
13
|
+
|
14
|
+
output = model_class.datatable(params)
|
15
|
+
|
16
|
+
# Render Encoded JSON
|
17
|
+
render :text => output.to_json, :layout => false
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
<% unless @pptions[:selectable].nil? or !@pptions[:selectable] -%>
|
2
|
+
<div id="rd_buttons">
|
3
|
+
<a id="rd_clear_selections" class="rd_disabled">Clear Selections</a>
|
4
|
+
<% unless @pptions[:selectable_actions].nil? -%>
|
5
|
+
<% @pptions[:selectable_actions].each do |sa| %>
|
6
|
+
<%= sa %>
|
7
|
+
<% end -%>
|
8
|
+
<% end -%>
|
9
|
+
</div>
|
10
|
+
<% end -%>
|
11
|
+
<table cellpadding="0" cellspacing="0" border="0" class="display" id="rdatatable">
|
12
|
+
<thead>
|
13
|
+
<tr>
|
14
|
+
<% @columns.each_pair do |key,col| -%>
|
15
|
+
<th width="<%= col[:width] %>"><%= col[:label] || key.to_s.humanize %></th>
|
16
|
+
<% end -%>
|
17
|
+
</tr>
|
18
|
+
</thead>
|
19
|
+
<tbody>
|
20
|
+
<tr>
|
21
|
+
<td colspan="<%= @columns.length.to_s %>" class="dataTables_empty">Loading...</td>
|
22
|
+
</tr>
|
23
|
+
</tbody>
|
24
|
+
<tfoot>
|
25
|
+
<tr>
|
26
|
+
<% @columns.each_pair do |key,col| -%>
|
27
|
+
<th><input type="text" name="search_<%= key.to_s %>" value="Search <%= col[:label] || key.to_s.humanize %>" class="search_init" rel="<%= @columns.keys.index(key) %>" /></th>
|
28
|
+
<% end -%>
|
29
|
+
</tr>
|
30
|
+
</tfoot>
|
31
|
+
</table>
|
32
|
+
|
33
|
+
<%= javascript_tag :defer => 'defer' do -%>
|
34
|
+
var asInitVals = new Array();
|
35
|
+
|
36
|
+
<% unless @pptions[:selectable].nil? or !@pptions[:selectable] -%>
|
37
|
+
var gaiSelected = [];
|
38
|
+
|
39
|
+
function rd_toggle_buttons() {
|
40
|
+
if( gaiSelected.length > 0 )
|
41
|
+
{
|
42
|
+
jQuery("#rd_buttons a").removeClass('rd_disabled');
|
43
|
+
jQuery("#rd_buttons a").addClass('rd_enabled');
|
44
|
+
}
|
45
|
+
else
|
46
|
+
{
|
47
|
+
jQuery("#rd_buttons a").removeClass('rd_enabled');
|
48
|
+
jQuery("#rd_buttons a").addClass('rd_disabled');
|
49
|
+
}
|
50
|
+
}
|
51
|
+
<% end -%>
|
52
|
+
|
53
|
+
function rd_bulk_edit_users() {
|
54
|
+
if( jQuery('#rd_bulk_edit_users').hasClass('rd_enabled') )
|
55
|
+
{
|
56
|
+
jQuery.prettyPhoto.open('/admin/projects/<%= @id %>/edit_users/' + gaiSelected + '?iframe=true&width=90%&height=90%');
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
60
|
+
jQuery(document).ready(function() {
|
61
|
+
var oTable = jQuery('#rdatatable').dataTable( {
|
62
|
+
|
63
|
+
/* Custom Options */
|
64
|
+
<% @jsoptions.each_pair do |k,v| -%>
|
65
|
+
"<%= k %>": <%= v %>,
|
66
|
+
<% end -%>
|
67
|
+
|
68
|
+
/* Visible / Hidden columns & Formatting */
|
69
|
+
"aoColumnDefs": [
|
70
|
+
<% @columns.each_pair do |name,attrs| -%>
|
71
|
+
<% if attrs[:type] == 'link' -%>
|
72
|
+
/* <%= name.to_s %> */ {
|
73
|
+
"fnRender": function ( oObj ) {
|
74
|
+
return '<a href="' + "<%= attrs[:link] %>".replace( /<%= attrs[:replace] %>/i, oObj.aData[<%= @columns.keys.index( attrs[:replace].to_sym ) %>] ) + '">' + oObj.aData[<%= @columns.keys.index( name.to_sym ) %>] + '</a>';
|
75
|
+
},
|
76
|
+
"aTargets": [ <%= @columns.keys.index( name ) %> ]
|
77
|
+
}<%= "," unless @columns.keys.last == name %>
|
78
|
+
<% elsif attrs[:type] == 'hidden' -%>
|
79
|
+
/* <%= name.to_s %> */ { "bVisible": false, "aTargets": [ <%= @columns.keys.index( name ) %> ] }<%= "," unless @columns.keys.last == name %>
|
80
|
+
<% else -%>
|
81
|
+
/* <%= name.to_s %> */ { "aTargets": [ <%= @columns.keys.index( name ) %> ] }<%= "," unless @columns.keys.last == name %>
|
82
|
+
<% end -%>
|
83
|
+
<% end -%>
|
84
|
+
],
|
85
|
+
|
86
|
+
<% unless @pptions[:selectable].nil? or !@pptions[:selectable] -%>
|
87
|
+
"fnRowCallback": function( nRow, aData, iDisplayIndex ) {
|
88
|
+
if ( jQuery.inArray(aData[0], gaiSelected) != -1 ) {
|
89
|
+
jQuery(nRow).addClass('row_selected');
|
90
|
+
}
|
91
|
+
return nRow;
|
92
|
+
},
|
93
|
+
<% end -%>
|
94
|
+
|
95
|
+
/* Boilerplate Options */
|
96
|
+
"sPaginationType": "full_numbers",
|
97
|
+
"aLengthMenu": [[10, 25, 50, 100, 500], [10, 25, 50, 100, 500]],
|
98
|
+
"bProcessing": true,
|
99
|
+
"bServerSide": true,
|
100
|
+
"sAjaxSource": '/rdtable/<%= @modelname %><%= "/#{@col_str}" %><%= @scope.nil? ? '' : "/#{@scope}" %><%= @id.nil? ? '' : "/#{@id}" %>'
|
101
|
+
} );
|
102
|
+
|
103
|
+
<% unless @pptions[:selectable].nil? or !@pptions[:selectable] -%>
|
104
|
+
jQuery('#rd_clear_selections').click( function () {
|
105
|
+
gaiSelected = [];
|
106
|
+
jQuery("#rdatatable tbody tr").removeClass('row_selected');
|
107
|
+
rd_toggle_buttons();
|
108
|
+
});
|
109
|
+
|
110
|
+
/* Click event handler */
|
111
|
+
jQuery('#rdatatable tbody tr').live('click', function () {
|
112
|
+
var aData = oTable.fnGetData( this );
|
113
|
+
var iId = aData[0];
|
114
|
+
|
115
|
+
if ( jQuery.inArray(iId, gaiSelected) == -1 )
|
116
|
+
{
|
117
|
+
gaiSelected[gaiSelected.length++] = iId;
|
118
|
+
}
|
119
|
+
else
|
120
|
+
{
|
121
|
+
gaiSelected = jQuery.grep(gaiSelected, function(value) {
|
122
|
+
return value != iId;
|
123
|
+
} );
|
124
|
+
}
|
125
|
+
|
126
|
+
jQuery(this).toggleClass('row_selected');
|
127
|
+
rd_toggle_buttons();
|
128
|
+
} );
|
129
|
+
<% end -%>
|
130
|
+
|
131
|
+
jQuery("tfoot input").keyup( function () {
|
132
|
+
/* Filter on the column (the index) of this element */
|
133
|
+
oTable.fnFilter( this.value, jQuery(this).attr('rel') );
|
134
|
+
gaiSelected = []; // clear the selection on filter
|
135
|
+
rd_toggle_buttons();
|
136
|
+
} );
|
137
|
+
|
138
|
+
/*
|
139
|
+
* Support functions to provide a little bit of 'user friendlyness' to the textboxes in
|
140
|
+
* the footer
|
141
|
+
*/
|
142
|
+
jQuery("tfoot input").each( function (i) {
|
143
|
+
asInitVals[i] = this.value;
|
144
|
+
} );
|
145
|
+
|
146
|
+
jQuery("tfoot input").focus( function () {
|
147
|
+
if ( this.className == "search_init" )
|
148
|
+
{
|
149
|
+
this.className = "";
|
150
|
+
this.value = "";
|
151
|
+
}
|
152
|
+
} );
|
153
|
+
|
154
|
+
jQuery("tfoot input").blur( function (i) {
|
155
|
+
if ( this.value == "" )
|
156
|
+
{
|
157
|
+
this.className = "search_init";
|
158
|
+
this.value = asInitVals[jQuery("tfoot input").index(this)];
|
159
|
+
}
|
160
|
+
} );
|
161
|
+
|
162
|
+
} );
|
163
|
+
<% end -%>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
Rails.application.routes.draw do
|
2
|
+
match 'rdtable/:model/:columns' => 'datatables#dataset', :as => 'datatable'
|
3
|
+
match 'rdtable/:model/:columns/:scope' => 'datatables#dataset', :as => 'datatable'
|
4
|
+
match 'rdtable/:model/:columns/:scope/:id' => 'datatables#dataset', :as => 'datatable'
|
5
|
+
end
|
data/datatables.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "datatables"
|
6
|
+
s.version = "1.0.0"
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.authors = ["Blair Williams","Brandon Toone"]
|
9
|
+
s.email = ["blair@caseproof.com","btoone@gmail.com"]
|
10
|
+
s.homepage = "http://blairwilliams.com/ruby-on-rails/datatables"
|
11
|
+
s.summary = %q{Datatables is a Rails 3 plugin that enables the easy creation of dynamic datatable views on top of any ActiveRecord model}
|
12
|
+
s.description = %q{Datatables is a Rails 3 plugin that enables the easy creation of dynamic datatable views on top of any ActiveRecord model. Datatables provides a simple helper that can be utilized in the view to automatically display a dynamic view on top of a model. Datatables handles the entire front end and backend support to do this. }
|
13
|
+
|
14
|
+
s.add_dependency('rails','>= 3.0.3')
|
15
|
+
s.add_dependency('jquery-rails')
|
16
|
+
|
17
|
+
s.license = 'MIT'
|
18
|
+
|
19
|
+
s.rubyforge_project = "datatables"
|
20
|
+
|
21
|
+
s.files = `git ls-files`.split("\n")
|
22
|
+
#s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
23
|
+
#s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
24
|
+
#s.require_paths = ["app","config","lib"]
|
25
|
+
end
|
data/lib/datatables.rb
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
module Datatables
|
2
|
+
require 'datatables/engine' if defined?(Rails) && Rails::VERSION::MAJOR == 3
|
3
|
+
require 'datatables/activerecord_methods' if defined?(Rails) && Rails::VERSION::MAJOR == 3
|
4
|
+
require 'datatables/datatable_helpers' if defined?(Rails) && Rails::VERSION::MAJOR == 3
|
5
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
# Adds the datatable method in ActiveRecord::Base, which sets up the backend for the datatable javascript
|
2
|
+
#
|
3
|
+
class << ActiveRecord::Base
|
4
|
+
def datatable( params )
|
5
|
+
curr_model = self
|
6
|
+
table_name = curr_model.table_name
|
7
|
+
|
8
|
+
if curr_model.metafied?
|
9
|
+
metas = curr_model.metafied_attrs || []
|
10
|
+
else
|
11
|
+
metas = []
|
12
|
+
end
|
13
|
+
|
14
|
+
sql_opts = { :select => [], :limit => "", :order => "", :joins => [], :conditions => "" }
|
15
|
+
columns = []
|
16
|
+
full_columns = []
|
17
|
+
|
18
|
+
dscope = params[:scope] || nil
|
19
|
+
dcols = params[:columns].split(',')
|
20
|
+
did = params[:id]
|
21
|
+
|
22
|
+
dcols.each do |col|
|
23
|
+
col = col.split(':')
|
24
|
+
if col.length > 1 # association (already assumed we're joined within a scope)
|
25
|
+
col_fmt = "`#{col[1].to_s}`.`#{col[2].to_s}`"
|
26
|
+
elsif metas.include? col.first.to_sym
|
27
|
+
col_fmt = "`m_#{col.first.to_s}`.`meta_value`"
|
28
|
+
else
|
29
|
+
col_fmt = "`#{table_name.to_s}`.`#{col.first.to_s}`"
|
30
|
+
end
|
31
|
+
|
32
|
+
columns.push col.first.to_s
|
33
|
+
full_columns.push col_fmt
|
34
|
+
sql_opts[:select].push "#{col_fmt} as #{col.first.to_s}"
|
35
|
+
end
|
36
|
+
|
37
|
+
# Paging
|
38
|
+
if params['iDisplayStart'] and params['iDisplayLength'] != '-1'
|
39
|
+
sql_opts[:limit] = "#{params['iDisplayStart']},#{params['iDisplayLength']}"
|
40
|
+
end
|
41
|
+
|
42
|
+
# Ordering
|
43
|
+
if params['iSortCol_0']
|
44
|
+
orders = []
|
45
|
+
i = 0
|
46
|
+
while i < params['iSortingCols'].to_i do
|
47
|
+
if params['bSortable_' + params['iSortCol_' + i.to_s]] == "true"
|
48
|
+
# Make sure the order works for metafied columns and normal columns
|
49
|
+
col = full_columns[ params['iSortCol_' + i.to_s].to_i ]
|
50
|
+
orders.push( "#{col} #{params['sSortDir_' + i.to_s]}" )
|
51
|
+
end
|
52
|
+
i += 1
|
53
|
+
end
|
54
|
+
sql_opts[:order] = orders.join(", ") unless orders.empty?
|
55
|
+
end
|
56
|
+
|
57
|
+
# Searching
|
58
|
+
search_str = ""
|
59
|
+
searches = []
|
60
|
+
if params['sSearch'] and !params['sSearch'].empty?
|
61
|
+
full_columns.each_with_index do |col,i|
|
62
|
+
searches.push( "#{col} LIKE '%#{params['sSearch']}%'" )
|
63
|
+
end
|
64
|
+
search_str = searches.join(' OR ') unless searches.empty?
|
65
|
+
end
|
66
|
+
|
67
|
+
# Filtering
|
68
|
+
filter_str = ""
|
69
|
+
filters = []
|
70
|
+
full_columns.each_with_index do |col,i|
|
71
|
+
if params['bSearchable_' + i.to_s] == "true" and !params['sSearch_' + i.to_s].empty?
|
72
|
+
filters.push( "#{col} LIKE '%#{params['sSearch_' + i.to_s]}%'" )
|
73
|
+
end
|
74
|
+
end
|
75
|
+
filter_str = filters.join(' AND ') unless filters.empty?
|
76
|
+
|
77
|
+
# Pull Searching & Filtering into where
|
78
|
+
if !searches.empty? and !filters.empty?
|
79
|
+
sql_opts[:conditions] = "(#{search_str}) AND #{filter_str}"
|
80
|
+
elsif !searches.empty?
|
81
|
+
sql_opts[:conditions] = search_str
|
82
|
+
elsif !filters.empty?
|
83
|
+
sql_opts[:conditions] = filter_str
|
84
|
+
end
|
85
|
+
|
86
|
+
# Query
|
87
|
+
if dscope.nil?
|
88
|
+
# Scope model
|
89
|
+
records = curr_model.select( sql_opts[:select] ).limit( sql_opts[:limit] ).order( sql_opts[:order] ).where( sql_opts[:conditions] ).joins(sql_opts[:joins])
|
90
|
+
# Records Found
|
91
|
+
filtered_total = curr_model.count( :select => "*", :conditions => sql_opts[:conditions], :joins => sql_opts[:joins] )
|
92
|
+
# Total Found
|
93
|
+
total = curr_model.count( :select => "*" )
|
94
|
+
elsif params[:id].nil?
|
95
|
+
# Scope model
|
96
|
+
records = curr_model.send( dscope.to_s ).select( sql_opts[:select] ).limit( sql_opts[:limit] ).order( sql_opts[:order] ).where( sql_opts[:conditions] ).joins(sql_opts[:joins])
|
97
|
+
# Records Found
|
98
|
+
filtered_total = curr_model.send( dscope.to_s ).count( :select => "*", :conditions => sql_opts[:conditions], :joins => sql_opts[:joins] )
|
99
|
+
# Total Found
|
100
|
+
total = curr_model.send( dscope.to_s ).count( :select => "*" )
|
101
|
+
else
|
102
|
+
# Scope model
|
103
|
+
records = curr_model.send( dscope.to_s, params[:id] ).select( sql_opts[:select] ).limit( sql_opts[:limit] ).order( sql_opts[:order] ).where( sql_opts[:conditions] ).joins(sql_opts[:joins])
|
104
|
+
# Records Found
|
105
|
+
filtered_total = curr_model.send( dscope.to_s, params[:id] ).count( :select => "*", :conditions => sql_opts[:conditions], :joins => sql_opts[:joins] )
|
106
|
+
# Total Found
|
107
|
+
total = curr_model.send( dscope.to_s, params[:id] ).count( :select => "*" )
|
108
|
+
end
|
109
|
+
|
110
|
+
# Build Output Data Structure
|
111
|
+
output = { "sEcho" => params['sEcho'],
|
112
|
+
"iTotalRecords" => total,
|
113
|
+
"iTotalDisplayRecords" => filtered_total,
|
114
|
+
"aaData" => [] }
|
115
|
+
|
116
|
+
records.each do |a_row|
|
117
|
+
row = []
|
118
|
+
columns.each_with_index do |col,i|
|
119
|
+
if col == "version" # Special output formatting for version column
|
120
|
+
row.push( a_row[ col ]=="0" ? '-' : a_row[ col ] )
|
121
|
+
elsif col != ' ' # General Output
|
122
|
+
row.push( a_row[ col ])
|
123
|
+
end
|
124
|
+
end
|
125
|
+
output['aaData'].push(row)
|
126
|
+
end
|
127
|
+
|
128
|
+
output
|
129
|
+
end
|
130
|
+
end
|