rails-datatables 0.0.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.
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Joel Quenneville
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,142 @@
1
+ # rails-datatables
2
+
3
+ Datatables is a nifty jquery plugin that adds the ability to paginate, sort, and search your html tables. When dealing with large tables (more than a couple hundred rows) however, we run into performance issues. These can be fixed by using server-side pagination, but this breaks some datatables functionality.
4
+
5
+ `rails-datatables` is a wrapper around datatable's ajax methods that allow synchronization with server-side pagination in a rails app. It was inspired by this [railscast](http://railscasts.com/episodes/340-datatables). I needed to implement a similar solution in a couple projects I was working on so I extracted it out into a gem.
6
+
7
+ ## Installation
8
+
9
+ Add these lines to your application's Gemfile:
10
+
11
+ gem 'jquery-datatables-rails'
12
+ gem 'rails-datatables'
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ ## Usage
19
+ *The following examples assume that we are setting up rails-datatables for an index of users from a `User` model*
20
+ ### Model
21
+ Run the following command:
22
+
23
+ $ rails generate ajaxdatatable User
24
+
25
+ This will generate a file named `users_datatable.rb` in `app/datatables`. Open the file and customize in the functions as directed by the comments
26
+
27
+ #### Initializer
28
+ ```ruby
29
+ def initialize(view)
30
+ @model_name = User
31
+ @columns = # insert array of column names here
32
+ @searchable_columns = #insert array of columns that will be searched
33
+ super(view)
34
+ end
35
+ ```
36
+
37
+ * For `@columns`, assign an array of the database columns that correspond to the columns in our view table. For example `[users.f_name, users.l_name, users.bio]`. This array is used for sorting by various columns
38
+
39
+ * For `@searchable_columns`, assign an array of the database columns that you want searchable by datatables. For example `[users.f_name, users.l_name]`
40
+
41
+ This gives us:
42
+ ```ruby
43
+ def initialize(view)
44
+ @model_name = User
45
+ @columns = [users.f_name, users.l_name, users.bio]
46
+ @searchable_columns = [users.f_name, users.l_name]
47
+ super(view)
48
+ end
49
+ ```
50
+
51
+ #### Data
52
+ ```ruby
53
+ def data
54
+ users.map do |user|
55
+ [
56
+ # comma separated list of the values for each cell of a table row
57
+ ]
58
+ end
59
+ end
60
+ ```
61
+
62
+ This method builds a 2d array that is used by datatables to construct the html table. Insert the values you want on each column.
63
+
64
+ ```ruby
65
+ def data
66
+ users.map do |user|
67
+ [
68
+ user.f_name,
69
+ user.l_name,
70
+ user.bio
71
+ ]
72
+ end
73
+ end
74
+ ```
75
+
76
+ #### Get Raw Records
77
+ ```ruby
78
+ def get_raw_records
79
+ # insert query here
80
+ end
81
+ ```
82
+
83
+ This is where your query goes.
84
+
85
+ ```ruby
86
+ def get_raw_records
87
+ User.all
88
+ end
89
+ ```
90
+
91
+ ### Controller
92
+ Set up the controller to respond to JSON
93
+
94
+ ```ruby
95
+ def index
96
+ respond_to do |format|
97
+ format.html
98
+ format.json { render json: UsersDatatable.new(view_context) }
99
+ end
100
+ end
101
+ ```
102
+
103
+ ### View
104
+ * Set up an html `<table>` with a `<thead>` and `<tbody>`
105
+ * Add in your table headers if desired
106
+ * Don't add any rows to the body of the table, datatables does this automatically
107
+ * Add a data attribute to the `<table>` tag with the url of the JSON feed
108
+
109
+ The resulting view may look like this:
110
+
111
+ ```erb
112
+ <table id="user-table", data-source="<%= users_path(format: :json) %>">
113
+ <thead>
114
+ <tr>
115
+ <th>First Name</th>
116
+ <th>Last Name</th>
117
+ <th>Brief Bio</th>
118
+ </tr>
119
+ </thead>
120
+ <tbody>
121
+ </tbody>
122
+ </table>
123
+ ```
124
+
125
+ ### Javascript
126
+ Finally, the javascript to tie this all together. In the appropriate `js.coffee` file:
127
+
128
+ ```coffeescript
129
+ $ ->
130
+ $('#users-table').dataTable
131
+ bProcessing: true
132
+ bServerSide: true
133
+ sAjaxSource: $('#users-table').data('source')
134
+ ```
135
+
136
+ ## Contributing
137
+
138
+ 1. Fork it
139
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
140
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
141
+ 4. Push to the branch (`git push origin my-new-feature`)
142
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+ task default: :spec
@@ -0,0 +1,8 @@
1
+ class AjaxdatatableGenerator < Rails::Generators::Base
2
+ source_root File.expand_path('../templates', __FILE__)
3
+ argument :model, type: :string
4
+
5
+ def generate_ajaxdatatable
6
+ template 'datatable.rb', File.join('app/datatables', "#{model.tableize}_datatable.rb")
7
+ end
8
+ end
@@ -0,0 +1,33 @@
1
+ class <%= model.classify.pluralize %>Datatable < RailsDatatables
2
+
3
+ def initialize(view)
4
+ @model_name = <%= model.classify %>
5
+ @columns = # insert array of column names here
6
+ @searchable_columns = #insert array of columns that will be searched
7
+ super(view)
8
+ end
9
+
10
+ private
11
+
12
+ def data
13
+ <%= model.tableize %>.map do |<%= model.tableize.singularize %>|
14
+ [
15
+ # comma separated list of the values for each cell of a table row
16
+ ]
17
+ end
18
+ end
19
+
20
+ def <%= model.tableize %>
21
+ @<%= model.tableize %> ||= fetch_records
22
+ end
23
+
24
+ def get_raw_records
25
+ # insert query here
26
+ end
27
+
28
+ def get_raw_record_count
29
+ search_records(get_raw_records).count
30
+ end
31
+
32
+ # ==== Insert 'presenter'-like methods below if necessary
33
+ end
@@ -0,0 +1,8 @@
1
+ class <%= model.classify.pluralize %>FilterDatatable < <%= model.classify.pluralize %>Datatable
2
+
3
+ private
4
+
5
+ def get_raw_records
6
+ # insert query here
7
+ end
8
+ end
@@ -0,0 +1,96 @@
1
+ # require 'rails'
2
+
3
+ class RailsDatatables
4
+
5
+ class MethodError < StandardError; end
6
+
7
+ VERSION = '0.0.1'
8
+
9
+ attr_reader :columns, :model_name, :searchable_columns
10
+
11
+ def initialize(view)
12
+ @view = view
13
+ end
14
+
15
+ def method_missing(meth, *args, &block)
16
+ @view.send(meth, *args, &block)
17
+ end
18
+
19
+ def as_json(options = {})
20
+ {
21
+ sEcho: params[:sEcho].to_i,
22
+ iTotalRecords: @model_name.count,
23
+ iTotalDisplayRecords: filtered_record_count,
24
+ aaData: data
25
+ }
26
+ end
27
+
28
+ private
29
+
30
+ def data
31
+ raise MethodError, "The method `data' is not defined."
32
+ end
33
+
34
+ def get_raw_records
35
+ raise MethodError, "The method `get_raw_records' is not defined."
36
+ end
37
+
38
+ def filtered_record_count
39
+ search_records(get_raw_records).count
40
+ end
41
+
42
+ def fetch_records
43
+ search_records(sort_records(paginate_records(get_raw_records)))
44
+ end
45
+
46
+ def paginate_records(records)
47
+ records.offset((page - 1) * per_page).limit(per_page)
48
+ end
49
+
50
+ def sort_records(records)
51
+ records.order("#{sort_column} #{sort_direction}")
52
+ end
53
+
54
+ def search_records(records)
55
+ if params[:sSearch].present?
56
+ value = params[:sSearch]
57
+ conditions = @searchable_columns.map do |column|
58
+ search_condition(column, value)
59
+ end
60
+ conditions = conditions.reduce(:or)
61
+ records = records.where(conditions)
62
+ end
63
+ conditions = @columns.each_with_index.map do |column, index|
64
+ value = params[:"sSearch_#{index}"]
65
+ search_condition(column, value) if value.present?
66
+ end
67
+ conditions = conditions.compact.reduce(:and)
68
+ records = records.where(conditions) if conditions.present?
69
+ records
70
+ end
71
+
72
+ def search_condition(column, value)
73
+ column = column.split('.').last
74
+ column_hash = @model_name.columns_hash[column]
75
+ if column_hash && [:string, :text].include?(column_hash.type)
76
+ return @model_name.arel_table[column].matches("%#{value}%")
77
+ end
78
+ @model_name.arel_table[column].eq(value)
79
+ end
80
+
81
+ def page
82
+ params[:iDisplayStart].to_i/per_page + 1
83
+ end
84
+
85
+ def per_page
86
+ params[:iDisplayLength].to_i > 0 ? params[:iDisplayLength].to_i : 10
87
+ end
88
+
89
+ def sort_column
90
+ @columns[params[:iSortCol_0].to_i]
91
+ end
92
+
93
+ def sort_direction
94
+ params[:sSortDir_0] == "desc" ? "DESC" : "ASC"
95
+ end
96
+ end
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rails-datatables
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Joel Quenneville
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-04-20 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ description: A gem that simplifies using datatables and hundreds of records via ajax
31
+ email:
32
+ - joel.quenneville@collegeplus.org
33
+ executables: []
34
+ extensions: []
35
+ extra_rdoc_files: []
36
+ files:
37
+ - lib/generators/ajaxdatatable/ajaxdatatable_generator.rb
38
+ - lib/generators/ajaxdatatable/templates/datatable.rb
39
+ - lib/generators/filterdatatable/templates/filter.rb
40
+ - lib/rails-datatables.rb
41
+ - LICENSE
42
+ - Rakefile
43
+ - README.md
44
+ homepage: ''
45
+ licenses: []
46
+ post_install_message:
47
+ rdoc_options: []
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirements: []
63
+ rubyforge_project:
64
+ rubygems_version: 1.8.24
65
+ signing_key:
66
+ specification_version: 3
67
+ summary: A wrapper around datatable's ajax methods that allow synchronization with
68
+ server-side pagination in a rails app
69
+ test_files: []