ajax-datatables-rails 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +23 -1132
  3. data/.travis.yml +36 -24
  4. data/Appraisals +14 -8
  5. data/CHANGELOG.md +32 -7
  6. data/Gemfile +2 -0
  7. data/README.md +400 -335
  8. data/Rakefile +2 -1
  9. data/ajax-datatables-rails.gemspec +8 -6
  10. data/doc/webpack.md +50 -0
  11. data/gemfiles/{rails_4.1.15.gemfile → rails_4.1.16.gemfile} +1 -1
  12. data/gemfiles/{rails_4.2.8.gemfile → rails_4.2.10.gemfile} +2 -1
  13. data/gemfiles/{rails_5.0.3.gemfile → rails_5.0.7.gemfile} +1 -1
  14. data/gemfiles/{rails_5.1.1.gemfile → rails_5.1.6.gemfile} +1 -1
  15. data/gemfiles/rails_5.2.0.gemfile +13 -0
  16. data/lib/ajax-datatables-rails.rb +3 -11
  17. data/lib/ajax-datatables-rails/base.rb +44 -24
  18. data/lib/ajax-datatables-rails/config.rb +3 -0
  19. data/lib/ajax-datatables-rails/datatable/column.rb +33 -125
  20. data/lib/ajax-datatables-rails/datatable/column/date_filter.rb +77 -0
  21. data/lib/ajax-datatables-rails/datatable/column/order.rb +29 -0
  22. data/lib/ajax-datatables-rails/datatable/column/search.rb +88 -0
  23. data/lib/ajax-datatables-rails/datatable/datatable.rb +10 -7
  24. data/lib/ajax-datatables-rails/datatable/simple_order.rb +17 -2
  25. data/lib/ajax-datatables-rails/datatable/simple_search.rb +3 -0
  26. data/lib/ajax-datatables-rails/orm/active_record.rb +14 -5
  27. data/lib/ajax-datatables-rails/version.rb +3 -1
  28. data/lib/ajax_datatables_rails.rb +15 -0
  29. data/lib/generators/datatable/config_generator.rb +2 -0
  30. data/lib/generators/datatable/templates/ajax_datatables_rails_config.rb +5 -0
  31. data/lib/generators/rails/datatable_generator.rb +6 -5
  32. data/lib/generators/rails/templates/datatable.rb +1 -15
  33. data/spec/ajax-datatables-rails/base_spec.rb +23 -26
  34. data/spec/ajax-datatables-rails/datatable/column_spec.rb +68 -23
  35. data/spec/ajax-datatables-rails/datatable/datatable_spec.rb +1 -1
  36. data/spec/ajax-datatables-rails/datatable/simple_order_spec.rb +29 -2
  37. data/spec/ajax-datatables-rails/datatable/simple_search_spec.rb +1 -1
  38. data/spec/ajax-datatables-rails/extended_spec.rb +3 -3
  39. data/spec/ajax-datatables-rails/orm/active_record_filter_records_spec.rb +94 -35
  40. data/spec/ajax-datatables-rails/orm/active_record_paginate_records_spec.rb +6 -6
  41. data/spec/ajax-datatables-rails/orm/active_record_sort_records_spec.rb +43 -0
  42. data/spec/ajax-datatables-rails/orm/active_record_spec.rb +1 -1
  43. data/spec/factories/user.rb +1 -1
  44. data/spec/install_oracle.sh +2 -2
  45. data/spec/spec_helper.rb +8 -3
  46. data/spec/support/datatable_cond_date.rb +5 -0
  47. data/spec/support/datatable_cond_numeric.rb +41 -0
  48. data/spec/support/datatable_cond_proc.rb +11 -0
  49. data/spec/support/datatable_cond_string.rb +23 -0
  50. data/spec/support/datatable_order_nulls_last.rb +5 -0
  51. data/spec/support/test_helpers.rb +13 -88
  52. metadata +28 -13
  53. data/lib/ajax-datatables-rails/datatable/column_date_filter.rb +0 -41
@@ -3,42 +3,52 @@ language: ruby
3
3
  sudo: required
4
4
  cache: bundler
5
5
  rvm:
6
- - 2.2.7
7
- - 2.3.4
6
+ - 2.2.10
7
+ - 2.3.7
8
8
  gemfile:
9
9
  - gemfiles/rails_4.0.13.gemfile
10
- - gemfiles/rails_4.1.15.gemfile
11
- - gemfiles/rails_4.2.8.gemfile
12
- - gemfiles/rails_5.0.3.gemfile
13
- - gemfiles/rails_5.1.1.gemfile
10
+ - gemfiles/rails_4.1.16.gemfile
11
+ - gemfiles/rails_4.2.10.gemfile
12
+ - gemfiles/rails_5.0.7.gemfile
13
+ - gemfiles/rails_5.1.6.gemfile
14
+ - gemfiles/rails_5.2.0.gemfile
14
15
  matrix:
15
16
  include:
16
- - rvm: 2.4.1
17
- gemfile: gemfiles/rails_4.2.8.gemfile
17
+ - rvm: 2.4.4
18
+ gemfile: gemfiles/rails_4.2.10.gemfile
18
19
  env: DB_ADAPTER=postgresql
19
- - rvm: 2.4.1
20
- gemfile: gemfiles/rails_5.0.3.gemfile
20
+ - rvm: 2.4.4
21
+ gemfile: gemfiles/rails_5.0.7.gemfile
21
22
  env: DB_ADAPTER=postgresql
22
- - rvm: 2.4.1
23
- gemfile: gemfiles/rails_5.1.1.gemfile
23
+ - rvm: 2.4.4
24
+ gemfile: gemfiles/rails_5.1.6.gemfile
24
25
  env: DB_ADAPTER=postgresql
25
- - rvm: 2.4.1
26
- gemfile: gemfiles/rails_4.2.8.gemfile
26
+ - rvm: 2.4.4
27
+ gemfile: gemfiles/rails_5.2.0.gemfile
28
+ env: DB_ADAPTER=postgresql
29
+ - rvm: 2.4.4
30
+ gemfile: gemfiles/rails_4.2.10.gemfile
31
+ env: DB_ADAPTER=mysql2
32
+ - rvm: 2.4.4
33
+ gemfile: gemfiles/rails_5.0.7.gemfile
27
34
  env: DB_ADAPTER=mysql2
28
- - rvm: 2.4.1
29
- gemfile: gemfiles/rails_5.0.3.gemfile
35
+ - rvm: 2.4.4
36
+ gemfile: gemfiles/rails_5.1.6.gemfile
30
37
  env: DB_ADAPTER=mysql2
31
- - rvm: 2.4.1
32
- gemfile: gemfiles/rails_5.1.1.gemfile
38
+ - rvm: 2.4.4
39
+ gemfile: gemfiles/rails_5.2.0.gemfile
33
40
  env: DB_ADAPTER=mysql2
34
- - rvm: 2.4.1
35
- gemfile: gemfiles/rails_4.2.8.gemfile
41
+ - rvm: 2.4.4
42
+ gemfile: gemfiles/rails_4.2.10.gemfile
43
+ env: DB_ADAPTER=oracle_enhanced
44
+ - rvm: 2.4.4
45
+ gemfile: gemfiles/rails_5.0.7.gemfile
36
46
  env: DB_ADAPTER=oracle_enhanced
37
- - rvm: 2.4.1
38
- gemfile: gemfiles/rails_5.0.3.gemfile
47
+ - rvm: 2.4.4
48
+ gemfile: gemfiles/rails_5.1.6.gemfile
39
49
  env: DB_ADAPTER=oracle_enhanced
40
- - rvm: 2.4.1
41
- gemfile: gemfiles/rails_5.1.1.gemfile
50
+ - rvm: 2.4.4
51
+ gemfile: gemfiles/rails_5.2.0.gemfile
42
52
  env: DB_ADAPTER=oracle_enhanced
43
53
  after_success:
44
54
  - bundle exec codeclimate-test-reporter
@@ -53,6 +63,8 @@ addons:
53
63
  - mysql-client-core-5.6
54
64
  - mysql-client-5.6
55
65
  before_install:
66
+ - gem update --system
67
+ - gem install bundler
56
68
  - sh -c "if [ '$DB_ADAPTER' = 'mysql2' ]; then mysql -e 'create database ajax_datatables_rails;'; fi"
57
69
  - sh -c "if [ '$DB_ADAPTER' = 'postgresql' ]; then psql -c 'create database ajax_datatables_rails;' -U postgres; fi"
58
70
  - sh -c "if [ '$DB_ADAPTER' = 'oracle_enhanced' ]; then ./spec/install_oracle.sh; fi"
data/Appraisals CHANGED
@@ -1,33 +1,39 @@
1
+ # frozen_string_literal: true
2
+
1
3
  RAILS_VERSIONS = {
2
4
  '4.0.13' => {
3
5
  'mysql2' => '~> 0.3.18',
4
6
  'activerecord-oracle_enhanced-adapter' => '~> 1.5.0'
5
7
  },
6
- '4.1.15' => {
8
+ '4.1.16' => {
7
9
  'mysql2' => '~> 0.3.18',
8
10
  'activerecord-oracle_enhanced-adapter' => '~> 1.5.0'
9
11
  },
10
- '4.2.8' => {
12
+ '4.2.10' => {
11
13
  'activerecord-oracle_enhanced-adapter' => '~> 1.6.0'
12
14
  },
13
- '5.0.3' => {
15
+ '5.0.7' => {
14
16
  'activerecord-oracle_enhanced-adapter' => '~> 1.7.0',
15
17
  'ruby-oci8' => ''
16
18
  },
17
- '5.1.1' => {
19
+ '5.1.6' => {
18
20
  'activerecord-oracle_enhanced-adapter' => '~> 1.8.0',
19
21
  'ruby-oci8' => ''
22
+ },
23
+ '5.2.0' => {
24
+ 'activerecord-oracle_enhanced-adapter' => '~> 5.2.0',
25
+ 'ruby-oci8' => ''
20
26
  }
21
- }
27
+ }.freeze
22
28
 
23
29
  RAILS_VERSIONS.each do |version, gems|
24
30
  appraise "rails_#{version}" do
25
31
  gem 'rails', version
26
- gems.each do |name, version|
27
- if version.empty?
32
+ gems.each do |name, gem_version|
33
+ if gem_version.empty?
28
34
  gem name
29
35
  else
30
- gem name, version
36
+ gem name, gem_version
31
37
  end
32
38
  end
33
39
  end
@@ -1,9 +1,30 @@
1
1
  # CHANGELOG
2
2
 
3
- ## 0.3.1
3
+ ## 0.4.1 (2018-05-06)
4
+
5
+ * Fix: Restore behavior of #filter method [Comment](https://github.com/jbox-web/ajax-datatables-rails/commit/07795fd26849ff1b3b567f4ce967f722907a45be#comments)
6
+ * Fix: Fix erroneous offset/start behavior [PR #264](https://github.com/jbox-web/ajax-datatables-rails/pull/264)
7
+ * Fix: "orderable" option has no effect [Issue #245](https://github.com/jbox-web/ajax-datatables-rails/issues/245)
8
+ * Fix: Fix undefined method #and [PR #235](https://github.com/jbox-web/ajax-datatables-rails/pull/235)
9
+ * Add: Add "order nulls last" option [PR #79](https://github.com/jbox-web/ajax-datatables-rails/pull/279)
10
+ * Change: Rename `additional_datas` method as `additional_data` [PR #251](https://github.com/jbox-web/ajax-datatables-rails/pull/251)
11
+ * Change: Added timezone support for daterange [PR #261](https://github.com/jbox-web/ajax-datatables-rails/pull/261)
12
+ * Change: Add # frozen_string_literal: true pragma
13
+ * Various improvements in internal API
14
+
15
+ **Note :** This is the last version to support Rails 4.0.x and Rails 4.1.x
16
+
17
+
18
+ ## 0.4.0 (2017-05-21)
19
+
20
+ **Warning:** this version is a **major break** from v0.3. The core has been rewriten to remove dependency on Kaminari (or WillPaginate).
21
+
22
+ It also brings a new (more natural) way of defining columns, based on hash definitions (and not arrays) and add some filtering options for column search. Take a look at the [README](https://github.com/jbox-web/ajax-datatables-rails#customize-the-generated-datatables-class) for more infos.
23
+
24
+ ## 0.3.1 (2015-07-13)
4
25
  * Adds `:oracle` as supported `db_adapter`. Thanks to [lutechspa](https://github.com/lutechspa) for this contribution.
5
26
 
6
- ## 0.3.0
27
+ ## 0.3.0 (2015-01-30)
7
28
  * Changes to the `sortable_columns` and `searchable_columns` syntax as it
8
29
  required us to do unnecessary guessing. New syntax is `ModelName.column_name`
9
30
  or `Namespace::ModelName.column_name`. Old syntax of `table_name.column_name`
@@ -14,7 +35,7 @@
14
35
  for this contribution.
15
36
  * Moves paginator settings to configuration initializer.
16
37
 
17
- ## 0.2.1
38
+ ## 0.2.1 (2014-11-26)
18
39
  * Fix count method to work with select statements under Rails 4.1. Thanks to
19
40
  [Jason Mitchell](https://github.com/mitchej123) for the contribution.
20
41
  * Edits to `README` documentation about the `options` hash. Thanks to
@@ -32,22 +53,22 @@ text-based columns and perform searches depending on the use of `:mysql2`,
32
53
  `:sqlite3` or `:pg`. Thanks to [M. Saiqul Haq](https://github.com/saiqulhaq)
33
54
  for contributing this feature.
34
55
 
35
- ## 0.2.0
56
+ ## 0.2.0 (2014-06-19)
36
57
  * This version works with jQuery dataTables ver. 1.10 and it's new API syntax.
37
58
  * Added `legacy` branch to repo. If your project is working with jQuery
38
59
  dataTables ver. 1.9, this is the branch you need to pull, or use the last
39
60
  `0.1.x` version of this gem.
40
61
 
41
- ## 0.1.2
62
+ ## 0.1.2 (2014-06-18)
42
63
  * Fixes `where` clause being built even when search term is an empty string.
43
64
  Thanks to [e-fisher](https://github.com/e-fisher) for spotting and fixing this.
44
65
 
45
- ## 0.1.1
66
+ ## 0.1.1 (2014-06-13)
46
67
  * Fixes problem on `searchable_columns` where the corresponding model is
47
68
  a composite model name, e.g. `UserData`, `BillingAddress`.
48
69
  Thanks to [iruca3](https://github.com/iruca3) for the fix.
49
70
 
50
- ## 0.1.0
71
+ ## 0.1.0 (2014-05-21)
51
72
  * A fresh start. Sets base class name to: `AjaxDatatablesRails::Base`.
52
73
  * Extracts pagination functions to mixable modules.
53
74
  * A user would have the option to stick to the base
@@ -65,3 +86,7 @@ Thanks to [iruca3](https://github.com/iruca3) for the fix.
65
86
  * Sets generator inside the `Rails` namespace. To generate an
66
87
  `AjaxDatatablesRails` child class, just execute the
67
88
  generator like this: `$ rails generate datatable NAME`.
89
+
90
+ ## 0.0.1 (2012-09-10)
91
+
92
+ First release!
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  gemspec
data/README.md CHANGED
@@ -8,73 +8,138 @@
8
8
  [![Test Coverage](https://codeclimate.com/github/jbox-web/ajax-datatables-rails/badges/coverage.svg)](https://codeclimate.com/github/jbox-web/ajax-datatables-rails/coverage)
9
9
  [![Dependency Status](https://gemnasium.com/jbox-web/ajax-datatables-rails.svg)](https://gemnasium.com/jbox-web/ajax-datatables-rails)
10
10
 
11
- > __Important__
11
+ **Important : This gem is targeted at DataTables version 1.10.x.**
12
+
13
+ It's tested against :
14
+
15
+ * Rails 4.0.13 / 4.1.16 / 4.2.10 / 5.0.7 / 5.1.6 / 5.2.0
16
+ * Ruby 2.2.10 / 2.3.7 / 2.4.4 / 2.5.1
17
+ * Postgresql 9.6
18
+ * MySQL 5.6
19
+ * Oracle XE 11.2 (thanks to [travis-oracle](https://github.com/cbandy/travis-oracle))
20
+ * SQLite3
21
+
22
+ ## Description
23
+
24
+ > [DataTables](https://datatables.net/) is a nifty jQuery plugin that adds the ability to paginate, sort, and search your html tables.
25
+ > When dealing with large tables (more than a couple of hundred rows) however, we run into performance issues.
26
+ > These can be fixed by using server-side pagination, but this breaks some DataTables functionality.
12
27
  >
13
- > This gem is targeted at Datatables version 1.10.x.
28
+ > `ajax-datatables-rails` is a wrapper around DataTables ajax methods that allow synchronization with server-side pagination in a Rails app.
29
+ > It was inspired by this [Railscast](http://railscasts.com/episodes/340-datatables).
30
+ > I needed to implement a similar solution in a couple projects I was working on, so I extracted a solution into a gem.
14
31
  >
15
- > It's tested against :
16
- > * Rails 4.0.13 / 4.1.15 / 4.2.8 / 5.0.2 / 5.1.0
17
- > * Ruby 2.2.7 / 2.3.4 / 2.4.1
18
- > * Postgresql
19
- > * MySQL
20
- > * Oracle XE 11.2 (thanks to [travis-oracle](https://github.com/cbandy/travis-oracle))
32
+ > Joel Quenneville (original author)
33
+ >
34
+ > I needed a good gem to manage a lot of DataTables so I chose this one :)
35
+ >
36
+ > Nicolas Rodriguez (current maintainer)
37
+
38
+ The final goal of this gem is to **generate a JSON** content that will be given to jQuery DataTables.
39
+ All the datatable customizations (header, tr, td, css classes, width, height, buttons, etc...) **must** take place in the [javascript definition](#5-wire-up-the-javascript) of the datatable.
40
+ jQuery DataTables is a very powerful tool with a lot of customizations available. Take the time to [read the doc](https://datatables.net/reference/option/).
21
41
 
22
- ## Description
23
42
 
24
- Datatables is a nifty jquery plugin that adds the ability to paginate, sort,
25
- and search your html tables. When dealing with large tables
26
- (more than a couple hundred rows) however, we run into performance issues.
27
- These can be fixed by using server-side pagination, but this breaks some
28
- datatables functionality.
43
+ ## Warning
29
44
 
30
- `ajax-datatables-rails` is a wrapper around datatable's ajax methods that allow
31
- synchronization with server-side pagination in a rails app. It was inspired by
32
- this [Railscast](http://railscasts.com/episodes/340-datatables). I needed to
33
- implement a similar solution in a couple projects I was working on, so I
34
- extracted a solution into a gem.
45
+ **Breaking changes :** the *v0.4* version is a **major break** from *v0.3*.
35
46
 
36
- ## ORM support
47
+ The core has been rewriten to remove dependency on [Kaminari](https://github.com/kaminari/kaminari) or [WillPaginate](https://github.com/mislav/will_paginate).
37
48
 
38
- Currently `AjaxDatatablesRails` only supports `ActiveRecord` as ORM for
39
- performing database queries.
49
+ It also brings a new (more natural) way of defining columns, based on hash definitions (and not arrays) and add some filtering options for column search.
50
+
51
+ [See below](#3-customize-the-generated-datatables-class) for more infos.
52
+
53
+ To migrate on the v0.4 you'll need to :
54
+
55
+ * update your DataTables classes to remove all the `extend` directives
56
+ * switch to hash definitions of `view_columns`
57
+ * update your views to declare your columns bindings ([See here](#5-wire-up-the-javascript))
40
58
 
41
- Adding support for `Sequel`, `Mongoid` and `MongoMapper` is a planned feature
42
- for this gem. If you'd be interested in contributing to speed development,
43
- please [open an issue](https://github.com/antillas21/ajax-datatables-rails/issues/new)
44
- and get in touch.
45
59
 
46
60
  ## Installation
47
61
 
48
62
  Add these lines to your application's Gemfile:
49
63
 
50
64
  ```ruby
51
- gem 'jquery-datatables-rails'
52
65
  gem 'ajax-datatables-rails'
53
66
  ```
54
67
 
55
68
  And then execute:
56
69
 
57
70
  ```sh
58
- $ bundle
71
+ $ bundle install
59
72
  ```
60
73
 
61
- The `jquery-datatables-rails` gem is listed as a convenience, to ease adding
62
- jQuery dataTables to your Rails project. You can always add the plugin assets
63
- manually via the assets pipeline. If you decide to use the
64
- `jquery-datatables-rails` gem, please refer to its installation instructions
65
- [here](https://github.com/rweng/jquery-datatables-rails).
74
+ We assume here that you have already installed [jQuery DataTables](https://datatables.net/).
75
+
76
+ You can install jQuery DataTables :
77
+
78
+ * with the [`jquery-datatables-rails`](https://github.com/rweng/jquery-datatables-rails) gem (which is a bit outdated)
79
+ * by adding the assets manually (in `vendor/assets`)
80
+ * with [Rails webpacker gem](https://github.com/rails/webpacker) (see [here](/doc/webpack.md) for more infos)
81
+
82
+
83
+ ## Configuration
84
+
85
+ Generate the `ajax-datatables-rails` config file with this command :
86
+
87
+ ```sh
88
+ $ bundle exec rails generate datatable:config
89
+ ```
90
+
91
+ Doing so, will create the `config/initializers/ajax_datatables_rails.rb` file with the following content :
92
+
93
+ ```ruby
94
+ AjaxDatatablesRails.configure do |config|
95
+ # available options for db_adapter are: :pg, :mysql, :mysql2, :sqlite, :sqlite3
96
+ # config.db_adapter = :pg
97
+
98
+ # Or you can use your rails environment adapter if you want a generic dev and production
99
+ # config.db_adapter = Rails.configuration.database_configuration[Rails.env]['adapter'].to_sym
100
+
101
+ # available options for orm are: :active_record, :mongoid
102
+ # config.orm = :active_record
103
+ end
104
+ ```
105
+
106
+ Uncomment the `config.db_adapter` line and set the corresponding value to your database and gem. This is all you need.
107
+
108
+ Uncomment the `config.orm` line to set `active_record or mongoid` if included in your project. It defaults to `active_record`.
66
109
 
110
+ #### Note
67
111
 
68
- ## Usage
112
+ Currently `AjaxDatatablesRails` only supports `ActiveRecord` as ORM for performing database queries.
69
113
 
70
- *The following examples assume that we are setting up ajax-datatables-rails for
71
- an index page of users from a `User` model, and that we are using postgresql as
72
- our db, because you __should be using it__, if not, please refer to the
73
- [Searching on non text-based columns](#searching-on-non-text-based-columns)
74
- entry in the Additional Notes section.*
114
+ Adding support for `Sequel`, `Mongoid` and `MongoMapper` is (more or less) a planned feature for this gem.
75
115
 
116
+ If you'd be interested in contributing to speed development, please [open an issue](https://github.com/antillas21/ajax-datatables-rails/issues/new) and get in touch.
76
117
 
77
- ### Generate
118
+
119
+ ## Quick start (in 5 steps)
120
+
121
+ The following examples assume that we are setting up `ajax-datatables-rails` for an index page of users from a `User` model,
122
+ and that we are using Postgresql as our db, because you **should be using it**. (It also works with other DB, see above, just be sure to have [configured the right adapter](#configuration))
123
+
124
+ The goal is to render a users table and display : `id`, `first name`, `last name`, `email`, and `bio` for each user.
125
+
126
+ Something like this:
127
+
128
+ |ID |First Name|Last Name|Email |Brief Bio|
129
+ |---|----------|---------|----------------------|---------|
130
+ | 1 |John |Doe |john.doe@example.net |Is your default user everywhere|
131
+ | 2 |Jane |Doe |jane.doe@example.net |Is John's wife|
132
+ | 3 |James |Doe |james.doe@example.net |Is John's brother and best friend|
133
+
134
+ Here the steps we're going through :
135
+
136
+ 1. [Generate the datatable class](#1-generate-the-datatable-class)
137
+ 2. [Build the View](#2-build-the-view)
138
+ 3. [Customize the generated Datatables class](#3-customize-the-generated-datatables-class)
139
+ 4. [Setup the Controller action](#4-setup-the-controller-action)
140
+ 5. [Wire up the Javascript](#5-wire-up-the-javascript)
141
+
142
+ ### 1) Generate the datatable class
78
143
 
79
144
  Run the following command:
80
145
 
@@ -88,31 +153,24 @@ Open the file and customize in the functions as directed by the comments.
88
153
  Take a look [here](#generator-syntax) for an explanation about the generator syntax.
89
154
 
90
155
 
91
- ### Build the View
92
-
93
- You should always start by the single source of truth, which is your html view. Suppose we need to render a users table and display: first name, last name, and bio for each user.
94
-
95
- Something like this:
96
-
97
- |First Name|Last Name|Brief Bio|
98
- |----------|---------|---------|
99
- |John |Doe |Is your default user everywhere|
100
- |Jane |Doe |Is John's wife|
101
- |James |Doe |Is John's brother and best friend|
156
+ ### 2) Build the View
102
157
 
158
+ You should always start by the single source of truth, which is your html view.
103
159
 
104
160
  * Set up an html `<table>` with a `<thead>` and `<tbody>`
105
161
  * Add in your table headers if desired
106
- * Don't add any rows to the body of the table, datatables does this automatically
162
+ * Don't add any rows to the body of the table, DataTables does this automatically
107
163
  * Add a data attribute to the `<table>` tag with the url of the JSON feed, in our case is the `users_path` as we're pointing to the `UsersController#index` action
108
164
 
109
165
 
110
166
  ```html
111
- <table id="users-table", data-source="<%= users_path(format: :json) %>">
167
+ <table id="users-datatable" data-source="<%= users_path(format: :json) %>">
112
168
  <thead>
113
169
  <tr>
170
+ <th>ID</th>
114
171
  <th>First Name</th>
115
172
  <th>Last Name</th>
173
+ <th>Email</th>
116
174
  <th>Brief Bio</th>
117
175
  </tr>
118
176
  </thead>
@@ -122,25 +180,22 @@ Something like this:
122
180
  ```
123
181
 
124
182
 
125
- ### Customize the generated Datatables class
183
+ ### 3) Customize the generated Datatables class
126
184
 
127
- ```ruby
128
- def view_columns
129
- # Declare strings in this format: ModelName.column_name
130
- # or in aliased_join_table.column_name format
131
- @view_columns ||= {}
132
- end
133
- ```
185
+ #### a. Declare columns mapping
134
186
 
135
- * In this method, add a list of the model(s) columns mapped to the data you need to present. In this case: `first_name`, `last_name` and `bio`.
187
+ First we need to declare in `view_columns` the list of the model(s) columns mapped to the data we need to present.
188
+ In this case: `id`, `first_name`, `last_name`, `email` and `bio`.
136
189
 
137
190
  This gives us:
138
191
 
139
192
  ```ruby
140
193
  def view_columns
141
194
  @view_columns ||= {
195
+ id: { source: "User.id" },
142
196
  first_name: { source: "User.first_name", cond: :like, searchable: true, orderable: true },
143
197
  last_name: { source: "User.last_name", cond: :like },
198
+ email: { source: "User.email" },
144
199
  bio: { source: "User.bio" },
145
200
  }
146
201
  end
@@ -152,52 +207,32 @@ end
152
207
 
153
208
  * `:like`, `:start_with`, `:end_with` for string or full text search
154
209
  * `:eq`, `:not_eq`, `:lt`, `:gt`, `:lteq`, `:gteq`, `:in` for numeric
155
- * `:date_range` for date range (only for Rails > 4.2.x)
210
+ * `:date_range` for date range (only for Rails > 4.2.x, see [here](#daterange-search))
156
211
  * `:null_value` for nil field
157
- * `Proc` for whatever
212
+ * `Proc` for whatever (see [here](https://github.com/ajahongir/ajax-datatables-rails-v-0-4-0-how-to/blob/master/app/datatables/city_datatable.rb) for real example)
158
213
 
159
- [See here](#searching-on-non-text-based-columns) for notes about the `view_columns` settings (if using something different from `postgres`).
160
- [Read these notes](#columns-syntax) about considerations for the `view_columns` method.
214
+ See [here](#columns-syntax) to get more details about columns definitions and how to play with associated models.
161
215
 
216
+ #### b. Map data
162
217
 
163
- #### Map data
164
-
165
- ```ruby
166
- def data
167
- records.map do |record|
168
- {
169
- # a hash of key value pairs
170
- }
171
- end
172
- end
173
- ```
218
+ Then we need to map the records retrieved by the `get_raw_records` method to the real values we want to display :
174
219
 
175
220
  ```ruby
176
221
  def data
177
222
  records.map do |record|
178
223
  {
224
+ id: record.id,
179
225
  first_name: record.first_name,
180
226
  last_name: record.last_name,
227
+ email: record.email,
181
228
  bio: record.bio,
182
- # 'DT_RowId' => record.id, # This will set the id attribute on the corresponding <tr> in the datatable
229
+ DT_RowId: record.id, # This will set the id attribute on the corresponding <tr> in the datatable
183
230
  }
184
231
  end
185
232
  end
186
233
  ```
187
-
188
234
  You can either use the v0.3 Array style for your columns :
189
235
 
190
- ```ruby
191
- def data
192
- records.map do |record|
193
- [
194
- # comma separated list of the values for each cell of a table row
195
- # example: record.first_name, record.last_name
196
- ]
197
- end
198
- end
199
- ```
200
-
201
236
  This method builds a 2d array that is used by datatables to construct the html
202
237
  table. Insert the values you want on each column.
203
238
 
@@ -205,34 +240,27 @@ table. Insert the values you want on each column.
205
240
  def data
206
241
  records.map do |record|
207
242
  [
243
+ record.id,
208
244
  record.first_name,
209
245
  record.last_name,
246
+ record.email,
210
247
  record.bio
211
248
  ]
212
249
  end
213
250
  end
214
251
  ```
215
252
 
216
- [See here](#using-view-helpers) if you need to use view helpers like `link_to`, `mail_to`, `resource_path`, etc.
253
+ The drawback of this method is that you can't pass the `DT_RowId` so it's tricky to set the id attribute on the corresponding `<tr>` in the datatable (need to be done on JS side).
217
254
 
255
+ [See here](#using-view-helpers) if you need to use view helpers like `link_to`, `mail_to`, etc...
218
256
 
219
- #### Get Raw Records
220
-
221
- ```ruby
222
- def get_raw_records
223
- # insert query here
224
- end
225
- ```
257
+ #### c. Get Raw Records
226
258
 
227
259
  This is where your query goes.
228
260
 
229
261
  ```ruby
230
262
  def get_raw_records
231
- # suppose we need all User records
232
- # Rails 4+
233
263
  User.all
234
- # Rails 3.x
235
- # User.scoped
236
264
  end
237
265
  ```
238
266
 
@@ -246,105 +274,17 @@ def get_raw_records
246
274
  end
247
275
  ```
248
276
 
249
- You can put any logic in `get_raw_records` [based on any parameters you inject](#options) in the `Datatable` object.
250
-
251
- > __IMPORTANT:__ Make sure to return an `ActiveRecord::Relation` object
252
- > as the end product of this method.
253
- >
254
- > Why? Because the result from this method, will be chained (for now)
255
- > to `ActiveRecord` methods for sorting, filtering and pagination.
256
-
277
+ You can put any logic in `get_raw_records` [based on any parameters you inject](#pass-options-to-the-datatable-class) in the `Datatable` object.
257
278
 
258
- #### Associated and nested models
279
+ **IMPORTANT :** Because the result of this method will be chained to `ActiveRecord` methods for sorting, filtering and pagination,
280
+ make sure to return an `ActiveRecord::Relation` object.
259
281
 
260
- The previous example has only one single model. But what about if you have
261
- some associated nested models and in a report you want to show fields from
262
- these tables.
282
+ #### d. Additional data
263
283
 
264
- Take an example that has an `Event, Course, Coursetype, Allocation, Teacher,
265
- Contact, Competency and CompetencyType` models. We want to have a datatables
266
- report which has the following column:
284
+ You can inject other key/value pairs in the rendered JSON by defining the `#additional_data` method :
267
285
 
268
286
  ```ruby
269
- 'coursetypes.name',
270
- 'courses.name',
271
- 'events.title',
272
- 'events.event_start',
273
- 'events.event_end',
274
- 'contacts.full_name',
275
- 'competency_types.name',
276
- 'events.status'
277
- ```
278
-
279
- We want to sort and search on all columns of the list. The related definition
280
- would be:
281
-
282
- ```ruby
283
- def view_columns
284
- @view_columns ||= [
285
- 'Coursetype.name',
286
- 'Course.name',
287
- 'Event.title',
288
- 'Event.event_start',
289
- 'Event.event_end',
290
- 'Contact.last_name',
291
- 'CompetencyType.name',
292
- 'Event.status'
293
- ]
294
- end
295
-
296
- def get_raw_records
297
- Event.joins(
298
- { course: :coursetype },
299
- { allocations: {
300
- teacher: [:contact, {competencies: :competency_type}]
301
- }
302
- }).distinct
303
- end
304
- ```
305
-
306
- __Some comments for the above code:__
307
-
308
- 1. In the `get_raw_records` method we have quite a complex query having one to
309
- many and may to many associations using the joins ActiveRecord method.
310
- The joins will generate INNER JOIN relations in the SQL query. In this case,
311
- we do not include all event in the report if we have events which is not
312
- associated with any model record from the relation.
313
-
314
- 2. To have all event records in the list we should use the `.includes` method,
315
- which generate LEFT OUTER JOIN relation of the SQL query.
316
- __IMPORTANT:__ Make sure to append `.references(:related_model)` with any
317
- associated model. That forces the eager loading of all the associated models
318
- by one SQL query, and the search condition for any column works fine.
319
- Otherwise the `:recordsFiltered => filter_records(get_raw_records).count(:all)`
320
- will generate 2 SQL queries (one for the Event model, and then another for the
321
- associated tables). The `:recordsFiltered => filter_records(get_raw_records).count(:all)`
322
- will use only the first one to return from the ActiveRecord::Relation object
323
- in `get_raw_records` and you will get an error message of __Unknown column
324
- 'yourtable.yourfield' in 'where clause'__ in case the search field value
325
- is not empty.
326
-
327
- So the query using the `.includes()` method is:
328
-
329
- ```ruby
330
- def get_raw_records
331
- Event.includes(
332
- { course: :coursetype },
333
- { allocations: {
334
- teacher: [:contact, { competencies: :competency_type }]
335
- }
336
- }
337
- ).references(:course).distinct
338
- end
339
- ```
340
-
341
-
342
- #### Additional datas
343
-
344
- You can inject other key/value pairs in the rendered JSON by defining the `#additional_datas` method :
345
-
346
- ```ruby
347
- def additional_datas
287
+ def additional_data
348
288
  {
349
289
  foo: 'bar'
350
290
  }
@@ -354,7 +294,7 @@ end
354
294
  Very useful with https://github.com/vedmack/yadcf to provide values for dropdown filters.
355
295
 
356
296
 
357
- ### Setup the Controller action
297
+ ### 4) Setup the Controller action
358
298
 
359
299
  Set the controller to respond to JSON
360
300
 
@@ -369,9 +309,9 @@ end
369
309
 
370
310
  Don't forget to make sure the proper route has been added to `config/routes.rb`.
371
311
 
372
- [See here](#options) to inject params in the `UserDatatable`.
312
+ [See here](#pass-options-to-the-datatable-class) if you need to inject params in the `UserDatatable`.
373
313
 
374
- ### Wire up the Javascript
314
+ ### 5) Wire up the Javascript
375
315
 
376
316
  Finally, the javascript to tie this all together. In the appropriate `coffee` file:
377
317
 
@@ -379,217 +319,307 @@ Finally, the javascript to tie this all together. In the appropriate `coffee` fi
379
319
  # users.coffee
380
320
 
381
321
  $ ->
382
- $('#users-table').dataTable
322
+ $('#users-datatable').dataTable
383
323
  processing: true
384
324
  serverSide: true
385
- ajax: $('#users-table').data('source')
325
+ ajax: $('#users-datatable').data('source')
386
326
  pagingType: 'full_numbers'
387
- # optional, if you want full pagination controls.
327
+ columns: [
328
+ {data: 'id'}
329
+ {data: 'first_name'}
330
+ {data: 'last_name'}
331
+ {data: 'email'}
332
+ {data: 'bio'}
333
+ ]
334
+ # pagingType is optional, if you want full pagination controls.
388
335
  # Check dataTables documentation to learn more about
389
336
  # available options.
390
337
  ```
391
338
 
392
339
  or, if you're using plain javascript:
340
+
393
341
  ```javascript
394
342
  // users.js
395
343
 
396
344
  jQuery(document).ready(function() {
397
- $('#users-table').dataTable({
345
+ $('#users-datatable').dataTable({
398
346
  "processing": true,
399
347
  "serverSide": true,
400
- "ajax": $('#users-table').data('source'),
348
+ "ajax": $('#users-datatable').data('source'),
401
349
  "pagingType": "full_numbers",
402
- // optional, if you want full pagination controls.
350
+ "columns": [
351
+ {"data": "id"},
352
+ {"data": "first_name"},
353
+ {"data": "last_name"},
354
+ {"data": "email"},
355
+ {"data": "bio"}
356
+ ]
357
+ // pagingType is optional, if you want full pagination controls.
403
358
  // Check dataTables documentation to learn more about
404
359
  // available options.
405
360
  });
406
361
  });
407
362
  ```
408
363
 
364
+ ## Advanced usage
409
365
 
410
- ### Additional Notes
411
-
412
- #### Columns syntax
366
+ ### Using view helpers
413
367
 
414
- Since version `0.3.0`, we are implementing a pseudo code way of declaring
415
- the array columns to use when querying the database.
368
+ Sometimes you'll need to use view helper methods like `link_to`, `mail_to`,
369
+ `edit_user_path`, `check_box_tag` and so on in the returned JSON representation returned by the [`data`](#b-map-data) method.
416
370
 
417
- Example. Suppose we have the following models: `User`, `PurchaseOrder`,
418
- `Purchase::LineItem` and we need to have several columns from those models
419
- available in our datatable to search and sort by.
371
+ To have these methods available to be used, this is the way to go:
420
372
 
421
373
  ```ruby
422
- # we use the ModelName.column_name notation to declare our columns
423
-
424
- def view_columns
425
- @view_columns ||= [
426
- 'User.first_name',
427
- 'User.last_name',
428
- 'PurchaseOrder.number',
429
- 'PurchaseOrder.created_at',
430
- 'Purchase::LineItem.quantity',
431
- 'Purchase::LineItem.unit_price',
432
- 'Purchase::LineItem.item_total'
433
- ]
434
- end
435
- ```
436
-
374
+ class MyCustomDatatable < AjaxDatatablesRails::Base
375
+ # either define them one-by-one
376
+ def_delegator :@view, :check_box_tag
377
+ def_delegator :@view, :link_to
378
+ def_delegator :@view, :mail_to
379
+ def_delegator :@view, :edit_user_path
437
380
 
438
- #### What if the datatable itself is namespaced?
381
+ # or define them in one pass
382
+ def_delegators :@view, :check_box_tag, :link_to, :mail_to, :edit_user_path
439
383
 
440
- Example: what if the datatable is namespaced into an `Admin` module?
384
+ # ... other methods (view_columns, get_raw_records...)
441
385
 
442
- ```ruby
443
- module Admin
444
- class PurchasesDatatable < AjaxDatatablesRails::Base
386
+ # now, you'll have these methods available to be used anywhere
387
+ def data
388
+ records.map do |record|
389
+ {
390
+ id: check_box_tag('users[]', record.id),
391
+ first_name: link_to(record.first_name, edit_user_path(record)),
392
+ last_name: record.last_name,
393
+ email: mail_to(record.email),
394
+ bio: record.bio
395
+ DT_RowId: record.id,
396
+ }
397
+ end
445
398
  end
446
399
  end
447
400
  ```
448
401
 
449
- Taking the same models and columns, we would define it like this:
402
+ If you want to keep things tidy in the data mapping method, you could use
403
+ [Draper](https://github.com/drapergem/draper) to define column mappings like below.
404
+
405
+ Example :
450
406
 
451
407
  ```ruby
452
- def view_columns
453
- @view_columns ||= [
454
- '::User.first_name',
455
- '::User.last_name',
456
- '::PurchaseOrder.number',
457
- '::PurchaseOrder.created_at',
458
- '::Purchase::LineItem.quantity',
459
- '::Purchase::LineItem.unit_price',
460
- '::Purchase::LineItem.item_total'
461
- ]
462
- end
463
- ```
408
+ ...
409
+ def data
410
+ records.map do |record|
411
+ {
412
+ id: record.decorate.check_box,
413
+ first_name: record.decorate.link_to,
414
+ last_name: record.decorate.last_name
415
+ email: record.decorate.email,
416
+ bio: record.decorate.bio
417
+ DT_RowId: record.id,
418
+ }
419
+ end
420
+ end
421
+ ...
464
422
 
465
- Pretty much like you would do it, if you were inside a namespaced controller.
423
+ class UserDecorator < ApplicationDecorator
424
+ delegate :last_name, :bio
466
425
 
426
+ def check_box
427
+ h.check_box_tag 'users[]', object.id
428
+ end
467
429
 
468
- #### Searching on non text-based columns
430
+ def link_to
431
+ h.link_to object.first_name, h.edit_user_path(object)
432
+ end
469
433
 
470
- It always comes the time when you need to add a non-string/non-text based
471
- column to the `@view_columns` array, so you can perform searches against
472
- these column types (example: numeric, date, time).
434
+ def email
435
+ h.mail_to object.email
436
+ end
473
437
 
474
- We recently added the ability to (automatically) typecast these column types
475
- and have this scenario covered. Please note however, if you are using
476
- something different from `postgresql` (with the `:pg` gem), like `mysql` or
477
- `sqlite`, then you need to add an initializer in your application's
478
- `config/initializers` directory.
438
+ # Just an example of a complex method you can add to you decorator
439
+ # To render it in a datatable just add a column 'dt_actions' in
440
+ # 'view_columns' and 'data' methods and call record.decorate.dt_actions
441
+ def dt_actions
442
+ links = []
443
+ links << h.link_to 'Edit', h.edit_user_path(object) if h.policy(object).update?
444
+ links << h.link_to 'Delete', h.user_path(object), method: :delete, remote: true if h.policy(object).destroy?
445
+ h.safe_join(links, '')
446
+ end
447
+ end
448
+ ```
479
449
 
480
- If you don't perform this step (again, if using something different from
481
- `postgresql`), your database will complain that it does not understand the
482
- default typecast used to enable such searches.
450
+ **Note :** On the long term it's much more cleaner than using `def_delegator` since decorators are reusable everywhere in your application :)
483
451
 
452
+ So we **strongly recommand you to use Draper decorators.** It will help keeping your DataTables class small and clean and keep focused on what they should do (mostly) : filtering records ;)
484
453
 
485
- #### Configuration initializer
454
+ **Note 2 :** The `def_delegator` might disappear in a near future : [#288 [RFC] Remove dependency on view_context](https://github.com/jbox-web/ajax-datatables-rails/issues/288).
455
+ You're invited to give your opinion :)
486
456
 
487
- You have two options to create this initializer:
457
+ ### Pass options to the datatable class
488
458
 
489
- * use the provided (and recommended) generator (and then just edit the file);
490
- * create the file from scratch.
459
+ An `AjaxDatatablesRails::Base` inherited class can accept an options hash at initialization. This provides room for flexibility when required.
491
460
 
492
- To use the generator, from the terminal execute:
461
+ Example:
493
462
 
494
- ```sh
495
- $ bundle exec rails generate datatable:config
496
- ```
463
+ ```ruby
464
+ # In the controller
465
+ def index
466
+ respond_to do |format|
467
+ format.html
468
+ format.json { render json: UserDatatable.new(view_context, user: current_user, from: 1.month.ago) }
469
+ end
470
+ end
497
471
 
498
- Doing so, will create the `config/initializers/ajax_datatables_rails.rb` file
499
- with the following content:
472
+ # The datatable class
473
+ class UnrespondedMessagesDatatable < AjaxDatatablesRails::Base
500
474
 
501
- ```ruby
502
- AjaxDatatablesRails.configure do |config|
503
- # available options for db_adapter are: :pg, :mysql, :mysql2, :sqlite, :sqlite3
504
- # config.db_adapter = :pg
475
+ # ... other methods (view_columns, data...)
505
476
 
506
- # available options for orm are: :active_record, :mongoid
507
- # config.orm = :active_record
508
- end
509
- ```
477
+ def user
478
+ @user ||= options[:user]
479
+ end
510
480
 
511
- Uncomment the `config.db_adapter` line and set the corresponding value to your
512
- database and gem. This is all you need.
481
+ def from
482
+ @from ||= options[:from].beginning_of_day
483
+ end
513
484
 
514
- Uncomment the `config.orm` line to set `active_record or mongoid` if
515
- included in your project. It defaults to `active_record`.
485
+ def to
486
+ @to ||= Date.today.end_of_day
487
+ end
516
488
 
517
- If you want to make the file from scratch, just copy the above code block into
518
- a file inside the `config/initializers` directory.
489
+ # We can now customize the get_raw_records method
490
+ # with the options we've injected
491
+ def get_raw_records
492
+ user.messages.unresponded.where(received_at: from..to)
493
+ end
519
494
 
495
+ end
496
+ ```
520
497
 
521
- #### Using view helpers
498
+ ### Columns syntax
522
499
 
523
- Sometimes you'll need to use view helper methods like `link_to`, `h`, `mailto`,
524
- `edit_resource_path` in the returned JSON representation returned by the `data`
525
- method.
500
+ You can mix several model in the same datatable.
526
501
 
527
- To have these methods available to be used, this is the way to go:
502
+ Suppose we have the following models: `User`, `PurchaseOrder`,
503
+ `Purchase::LineItem` and we need to have several columns from those models
504
+ available in our datatable to search and sort by.
528
505
 
529
506
  ```ruby
530
- class MyCustomDatatable < AjaxDatatablesRails::Base
531
- # either define them one-by-one
532
- def_delegator :@view, :link_to
533
- def_delegator :@view, :h
534
- def_delegator :@view, :mail_to
535
-
536
- # or define them in one pass
537
- def_delegators :@view, :link_to, :h, :mailto, :edit_resource_path, :other_method
507
+ # we use the ModelName.column_name notation to declare our columns
538
508
 
539
- # now, you'll have these methods available to be used anywhere
540
- # example: mapping the 2d jsonified array returned.
541
- def data
542
- records.map do |record|
543
- {
544
- first_name: link_to(record.fname, edit_resource_path(record)),
545
- email: mail_to(record.email),
546
- # other attributes
547
- }
548
- end
549
- end
509
+ def view_columns
510
+ @view_columns ||= {
511
+ first_name: 'User.first_name',
512
+ last_name: 'User.last_name',
513
+ order_number: 'PurchaseOrder.number',
514
+ order_created_at: 'PurchaseOrder.created_at',
515
+ quantity: 'Purchase::LineItem.quantity',
516
+ unit_price: 'Purchase::LineItem.unit_price',
517
+ item_total: 'Purchase::LineItem.item_total'
518
+ }
550
519
  end
551
520
  ```
552
521
 
522
+ ### Associated and nested models
553
523
 
554
- #### Options
524
+ The previous example has only one single model. But what about if you have
525
+ some associated nested models and in a report you want to show fields from
526
+ these tables.
555
527
 
556
- An `AjaxDatatablesRails::Base` inherited class can accept an options hash at
557
- initialization. This provides room for flexibility when required. Example:
528
+ Take an example that has an `Event, Course, CourseType, Allocation, Teacher,
529
+ Contact, Competency and CompetencyType` models. We want to have a datatables
530
+ report which has the following column:
558
531
 
559
532
  ```ruby
560
- class UnrespondedMessagesDatatable < AjaxDatatablesRails::Base
561
- # customized methods here
562
- end
563
-
564
- datatable = UnrespondedMessagesDatatable.new(view_context,
565
- { user: current_user, from: 1.month.ago }
566
- )
533
+ 'course_types.name'
534
+ 'courses.name'
535
+ 'contacts.full_name'
536
+ 'competency_types.name'
537
+ 'events.title'
538
+ 'events.event_start'
539
+ 'events.event_end'
540
+ 'events.status'
567
541
  ```
568
542
 
569
- So, now inside your class code, you can use those options like this:
570
-
543
+ We want to sort and search on all columns of the list.
544
+ The related definition would be :
571
545
 
572
546
  ```ruby
573
- # let's see an example
574
- def user
575
- @user ||= options[:user]
547
+ def view_columns
548
+ @view_columns ||= {
549
+ course_type: 'CourseType.name',
550
+ course_name: 'Course.name',
551
+ contact_name: 'Contact.full_name',
552
+ competency_type: 'CompetencyType.name',
553
+ event_title: 'Event.title',
554
+ event_start: 'Event.event_start',
555
+ event_end: 'Event.event_end',
556
+ event_status: 'Event.status',
557
+ }
576
558
  end
577
559
 
578
- def from
579
- @from ||= options[:from].beginning_of_day
560
+ def get_raw_records
561
+ Event.joins(
562
+ { course: :course_type },
563
+ { allocations: {
564
+ teacher: [:contact, { competencies: :competency_type }]
565
+ }
566
+ }).distinct
580
567
  end
568
+ ```
581
569
 
582
- def to
583
- @to ||= Date.today.end_of_day
584
- end
570
+ **Some comments for the above code :**
571
+
572
+ 1. In the `get_raw_records` method we have quite a complex query having one to
573
+ many and many to many associations using the joins ActiveRecord method.
574
+ The joins will generate INNER JOIN relations in the SQL query. In this case,
575
+ we do not include all event in the report if we have events which is not
576
+ associated with any model record from the relation.
577
+
578
+ 2. To have all event records in the list we should use the `.includes` method,
579
+ which generate LEFT OUTER JOIN relation of the SQL query.
585
580
 
581
+ **IMPORTANT :**
582
+
583
+ Make sure to append `.references(:related_model)` with any
584
+ associated model. That forces the eager loading of all the associated models
585
+ by one SQL query, and the search condition for any column works fine.
586
+ Otherwise the `:recordsFiltered => filter_records(get_raw_records).count(:all)`
587
+ will generate 2 SQL queries (one for the Event model, and then another for the
588
+ associated tables). The `:recordsFiltered => filter_records(get_raw_records).count(:all)`
589
+ will use only the first one to return from the ActiveRecord::Relation object
590
+ in `get_raw_records` and you will get an error message of **Unknown column
591
+ 'yourtable.yourfield' in 'where clause'** in case the search field value
592
+ is not empty.
593
+
594
+ So the query using the `.includes()` method is:
595
+
596
+ ```ruby
586
597
  def get_raw_records
587
- user.messages.unresponded.where(received_at: from..to)
598
+ Event.includes(
599
+ { course: :course_type },
600
+ { allocations: {
601
+ teacher: [:contact, { competencies: :competency_type }]
602
+ }
603
+ }).references(:course).distinct
588
604
  end
589
605
  ```
590
606
 
607
+ ### Default scope
608
+
609
+ See [DefaultScope is evil](https://rails-bestpractices.com/posts/2013/06/15/default_scope-is-evil/) and [#223](https://github.com/jbox-web/ajax-datatables-rails/issues/223) and [#233](https://github.com/jbox-web/ajax-datatables-rails/issues/233).
610
+
611
+ ### DateRange search
612
+
613
+ This feature works with [yadcf](https://github.com/vedmack/yadcf).
591
614
 
592
- #### Generator Syntax
615
+ To enable the date range search, for example `created_at` :
616
+
617
+ * add a 'created_at' `<th>` in your html
618
+ * declare your column in `view_columns` : `created_at: { source: 'Post.created_at', cond: :date_range, delimiter: '-yadcf_delim-' }`
619
+ * add it in `data` : `created_at: record.decorate.created_at`
620
+ * setup yadcf to make `created_at` search field a range
621
+
622
+ ### Generator Syntax
593
623
 
594
624
  Also, a class that inherits from `AjaxDatatablesRails::Base` is not tied to an
595
625
  existing model, module, constant or any type of class in your Rails app.
@@ -611,19 +641,54 @@ In the end, it's up to the developer which model(s), scope(s), relationship(s)
611
641
  (or else) to employ inside the datatable class to retrieve records from the
612
642
  database.
613
643
 
644
+ ### Creating indices for Postgresql
614
645
 
615
- ## Tutorial
646
+ In order to speed up the `ILIKE` queries that are executed when using the default configuration, you might want to consider adding some indices.
647
+ For postgresql, you are advised to use the [gin/gist index type](http://www.postgresql.org/docs/current/interactive/pgtrgm.html).
648
+ This makes it necessary to enable the postgrsql extension `pg_trgm`. Double check that you have this extension installed before trying to enable it.
649
+ A migration for enabling the extension and creating the indices could look like this:
616
650
 
617
- Tutorial for Integrating `ajax-datatables-rails` on Rails 4.
651
+ ```ruby
652
+ def change
653
+ enable_extension :pg_trgm
654
+ TEXT_SEARCH_ATTRIBUTES = ['your', 'attributes']
655
+ TABLE = 'your_table'
656
+
657
+ TEXT_SEARCH_ATTRIBUTES.each do |attr|
658
+ reversible do |dir|
659
+ dir.up do
660
+ execute "CREATE INDEX #{TABLE}_#{attr}_gin ON #{TABLE} USING gin(#{attr} gin_trgm_ops)"
661
+ end
662
+
663
+ dir.down do
664
+ remove_index TABLE.to_sym, name: "#{TABLE}_#{attr}_gin"
665
+ end
666
+ end
667
+ end
668
+ end
669
+ ```
618
670
 
619
- [Part-1 The-Installation](https://github.com/jbox-web/ajax-datatables-rails/wiki/Part-1----The-Installation)
671
+ ### Speedup JSON rendering
620
672
 
621
- [Part 2 The Datatables with ajax functionality](https://github.com/jbox-web/ajax-datatables-rails/wiki/Part-2-The-Datatables-with-ajax-functionality)
673
+ Install [yajl-ruby](https://github.com/brianmario/yajl-ruby), basically :
622
674
 
623
- The complete project code for this tutorial series is available on [github](https://github.com/trkrameshkumar/simple_app).
675
+ ```ruby
676
+ gem 'yajl-ruby', require: 'yajl'
677
+ ```
678
+
679
+ then
680
+
681
+ ```sh
682
+ $ bundle install
683
+ ```
684
+
685
+ That's all :) ([Automatically prefer Yajl or JSON backend over Yaml, if available](https://github.com/rails/rails/commit/63bb955a99eb46e257655c93dd64e86ebbf05651))
686
+
687
+ ## Tutorial
624
688
 
625
- Another sample project [code](https://github.com/ajahongir/ajax-datatables-rails-v-0-4-0-how-to). Its real world example.
689
+ You'll find a sample project [here](https://github.com/ajahongir/ajax-datatables-rails-v-0-4-0-how-to). Its real world example.
626
690
 
691
+ Filtering by JSONB column values : [#277](https://github.com/jbox-web/ajax-datatables-rails/issues/277)
627
692
 
628
693
  ## Contributing
629
694