effective_datatables 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +581 -0
  4. data/Rakefile +23 -0
  5. data/app/assets/images/effective_datatables/copy_csv_xls_pdf.swf +0 -0
  6. data/app/assets/javascripts/effective_datatables.bootstrap2.js +11 -0
  7. data/app/assets/javascripts/effective_datatables.js +12 -0
  8. data/app/assets/javascripts/effective_datatables/initialize.js.coffee +65 -0
  9. data/app/assets/javascripts/vendor/jquery.dataTables.columnFilter.js +829 -0
  10. data/app/assets/stylesheets/effective_datatables.bootstrap2.css.scss +8 -0
  11. data/app/assets/stylesheets/effective_datatables.css.scss +8 -0
  12. data/app/assets/stylesheets/effective_datatables/_overrides.scss +72 -0
  13. data/app/controllers/effective/datatables_controller.rb +36 -0
  14. data/app/helpers/effective_datatables_helper.rb +74 -0
  15. data/app/models/effective/access_denied.rb +17 -0
  16. data/app/models/effective/active_record_datatable_tool.rb +87 -0
  17. data/app/models/effective/array_datatable_tool.rb +66 -0
  18. data/app/models/effective/datatable.rb +352 -0
  19. data/app/views/effective/datatables/_datatable.html.haml +11 -0
  20. data/app/views/effective/datatables/_spacer_template.html +1 -0
  21. data/config/routes.rb +11 -0
  22. data/lib/effective_datatables.rb +32 -0
  23. data/lib/effective_datatables/engine.rb +20 -0
  24. data/lib/effective_datatables/version.rb +3 -0
  25. data/lib/generators/effective_datatables/install_generator.rb +17 -0
  26. data/lib/generators/templates/README +1 -0
  27. data/lib/generators/templates/effective_datatables.rb +23 -0
  28. data/lib/tasks/effective_datatables_tasks.rake +17 -0
  29. data/spec/dummy/README.rdoc +261 -0
  30. data/spec/dummy/Rakefile +7 -0
  31. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  32. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  33. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  34. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  35. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  36. data/spec/dummy/config.ru +4 -0
  37. data/spec/dummy/config/application.rb +59 -0
  38. data/spec/dummy/config/boot.rb +10 -0
  39. data/spec/dummy/config/database.yml +25 -0
  40. data/spec/dummy/config/environment.rb +5 -0
  41. data/spec/dummy/config/environments/development.rb +37 -0
  42. data/spec/dummy/config/environments/production.rb +67 -0
  43. data/spec/dummy/config/environments/test.rb +37 -0
  44. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  45. data/spec/dummy/config/initializers/inflections.rb +15 -0
  46. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  47. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  48. data/spec/dummy/config/initializers/session_store.rb +8 -0
  49. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  50. data/spec/dummy/config/locales/en.yml +5 -0
  51. data/spec/dummy/config/routes.rb +58 -0
  52. data/spec/dummy/db/development.sqlite3 +0 -0
  53. data/spec/dummy/db/schema.rb +16 -0
  54. data/spec/dummy/db/test.sqlite3 +0 -0
  55. data/spec/dummy/log/development.log +17 -0
  56. data/spec/dummy/log/test.log +1 -0
  57. data/spec/dummy/public/404.html +26 -0
  58. data/spec/dummy/public/422.html +26 -0
  59. data/spec/dummy/public/500.html +25 -0
  60. data/spec/dummy/public/favicon.ico +0 -0
  61. data/spec/dummy/script/rails +6 -0
  62. data/spec/effective_datatables_spec.rb +7 -0
  63. data/spec/spec_helper.rb +34 -0
  64. data/spec/support/factories.rb +1 -0
  65. metadata +217 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 414d2116620a9a9fc13a0bc1834558b06d962d45
4
+ data.tar.gz: 23396e31fee70831e41f9e90aec1d269c9009248
5
+ SHA512:
6
+ metadata.gz: abb7a4c4b53a0c3218ac24d07cea39fb245eac48d7c8f3764a1362005c7bd012fc20107fd8c6f81b82efcac168e0e6f6c5eee30754b009bc69a66c1a6f003a25
7
+ data.tar.gz: 80a229f44939b2d4762d53e412217443c3f8402fd3be82523e7013809530e517867252800d97e049ab93b19ad9afc4a63b9e98aa80bf11147adabf74940a7450
@@ -0,0 +1,20 @@
1
+ Copyright 2014 Code and Effect Inc.
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.
@@ -0,0 +1,581 @@
1
+ # Effective DataTables
2
+
3
+ Uniquely powerful server-side searching, sorting and filtering of any ActiveRecord or Array collection as well as post-rendered content displayed as a frontend jQuery Datatable.
4
+
5
+ Use a simple DSL in just one ruby file to implement all features
6
+
7
+ Search raw database tables and ruby post-rendered results at the same time
8
+
9
+ Packages the jQuery DataTables assets for use in a Rails 3.2.x & Rails 4.x application using Twitter Bootstrap 2 or 3
10
+
11
+ ## Getting Started
12
+
13
+ ```ruby
14
+ gem 'effective_datatables'
15
+ ```
16
+
17
+ Run the bundle command to install it:
18
+
19
+ ```console
20
+ bundle install
21
+ ```
22
+
23
+ Install the configuration file:
24
+
25
+ ```console
26
+ rails generate effective_datatables:install
27
+ ```
28
+
29
+ The generator will install an initializer which describes all configuration options.
30
+
31
+
32
+ Require the javascript on the asset pipeline by adding the following to your application.js:
33
+
34
+ ```ruby
35
+ # For use with Bootstrap3 (which is not included in this gem):
36
+ //= require effective_datatables
37
+
38
+ # For use with Bootstrap2 (which is not includled in this gem):
39
+ //= require effective_datatables.bootstrap2
40
+ ```
41
+
42
+ Require the stylesheet on the asset pipeline by adding the following to your application.css:
43
+
44
+ ```ruby
45
+ # For use with Bootstrap3 (which is not included in this gem):
46
+ *= require effective_datatables
47
+
48
+ # For use with Bootstrap2 (which is not not included in this gem):
49
+ *= require effective_datatables.bootstrap2
50
+ ```
51
+
52
+ ## Usage
53
+
54
+ We create a model, initialize it within our controller, then render it from a view
55
+
56
+ ### The Model
57
+
58
+ Start by creating a model in the `/app/models/effective/datatables/` directory.
59
+
60
+ Any `Effective::Datatable` models that exist in this directory will be automatically detected and 'just work'.
61
+
62
+ Below is a very simple example file, which we will expand upon later.
63
+
64
+ This model exists at `/app/models/effective/datatables/posts.rb`:
65
+
66
+ ```ruby
67
+ module Effective
68
+ module Datatables
69
+ class Posts < Effective::Datatable
70
+ table_column :id
71
+ table_column :user # if Post belongs_to :user
72
+ table_column :title
73
+ table_column :created_at
74
+
75
+ def collection
76
+ Post.all
77
+ end
78
+
79
+ end
80
+ end
81
+ end
82
+ ```
83
+
84
+ ### The Controller
85
+
86
+ We're going to display this DataTable on the posts#index action
87
+
88
+ ```ruby
89
+ class PostsController < ApplicationController
90
+ def index
91
+ @datatable = Effective::Datatables::Posts.new()
92
+ end
93
+ end
94
+ ```
95
+
96
+ ### The View
97
+
98
+ Here we just render the datatable:
99
+
100
+ ```erb
101
+ <h1>All Posts</h1>
102
+
103
+ <% if @datatable.collection.length == 0 %>
104
+ <p>There are no posts.</p>
105
+ <% else %>
106
+ <%= render_datatable(@datatable) %>
107
+ <% end %>
108
+ ```
109
+
110
+ ## How It Works
111
+
112
+ When the jQuery DataTable is first initialized on the front-end, it makes an AJAX request back to the server asking for data.
113
+
114
+ The effective_datatables gem intercepts this request and returns the appropriate results.
115
+
116
+ Whenever a search, sort, filter or pagination is initiated on the front end, that request is interpretted by the server and the appropriate results returned.
117
+
118
+ Due to the unique search/filter ability of this gem, a mix of raw database tables and processed results may be worked with at the same time.
119
+
120
+
121
+ ### Effective::Datatable Model & DSL
122
+
123
+ Once your controller and view are set up to render a Datatable, the model is the central point to configure all behaviour.
124
+
125
+ This single model file contains just 1 required method and responds to only 3 DSL commands.
126
+
127
+ Each `Effective::Datatable` model must be defined in the `/app/models/effective/datatables/` directory.
128
+
129
+ For example: `/app/models/effective/datatables/posts.rb`:
130
+
131
+ ```ruby
132
+ module Effective
133
+ module Datatables
134
+ class Posts < Effective::Datatable
135
+ default_order :created_at, :desc
136
+
137
+ table_column :id, :visible => false
138
+
139
+ table_column :created_at, :width => '25%' do |post|
140
+ post.created_at.strftime("%Y-%m-%d %H:%M:%S")
141
+ end
142
+
143
+ table_column :updated_at, :proc => Proc.new { |post| nicetime(post.updated_at) } # just a standard helper as defined in helpers/application_helper.rb
144
+
145
+ table_column :user
146
+
147
+ table_column :post_category_id, :filter => {:type => :select, :values => Proc.new { PostCategory.all } } do |post|
148
+ post.post_category.name.titleize
149
+ end
150
+
151
+ array_column :comments do |post|
152
+ content_tag(:ul) do
153
+ post.comments.where(:archived => false).map do |comment|
154
+ content_tag(:li, comment.title)
155
+ end.join('').html_safe
156
+ end
157
+ end
158
+
159
+ table_column :title, :label => 'Post Title'
160
+ table_column :actions, :sortable => false, :filter => false, :partial => '/posts/actions'
161
+
162
+ def collection
163
+ Post.where(:archived => false).includes(:post_category)
164
+ end
165
+
166
+ end
167
+ end
168
+ end
169
+ ```
170
+
171
+ ### The collection
172
+
173
+ A required method `def collection` must be defined to return the base ActiveRecord collection.
174
+
175
+ It can be as simple or as complex as you'd like:
176
+
177
+ ```ruby
178
+ def collection
179
+ Posts.all
180
+ end
181
+ ```
182
+
183
+ or (complex example):
184
+
185
+ ```ruby
186
+ def collection
187
+ User.unscoped.uniq
188
+ .joins('LEFT JOIN customers ON customers.user_id = users.id')
189
+ .select('users.*')
190
+ .select('customers.stripe_customer_id AS stripe_customer_id')
191
+ .includes(:addresses)
192
+ end
193
+ ```
194
+
195
+ ## table_column
196
+
197
+ This is the main DSL method that you will interact with.
198
+
199
+ table_column defines a 1:1 mapping between a SQL database table column and a frontend jQuery Datatables table column. It creates a column.
200
+
201
+ Options may be passed to specify the display, search, sort and filter behaviour for that column.
202
+
203
+ When the given name of the table_column matches an ActiveRecord attribute, the options are set intelligently based on the underlying datatype.
204
+
205
+ ```ruby
206
+ # The name of the table column as per the Database
207
+ # This column is detected as an Integer, therefore it is :type => :integer
208
+ # Any SQL used to search this field will take the form of "id = ?"
209
+ table_column :id
210
+
211
+ # As per our 'complex' example above, using the .select('customers.stripe_customer_id AS stripe_customer_id') syntax to create a faux database table
212
+ # This column is detected as a String, therefore it is :type => :string
213
+ # Any SQL used to search this field will take the form of "customers.stripe_customer_id ILIKE %?%"
214
+ table_column :stripe_customer_id, :column => 'customers.stripe_customer_id'
215
+
216
+ # The name of the table column as per the Database
217
+ # This column is detected as a DateTime, therefore it is :type => :datetime
218
+ # Any SQL used to search this field will take the form of
219
+ # "to_char(#{column} AT TIME ZONE 'GMT', 'YYYY-MM-DD HH24:MI') ILIKE '%?%'"
220
+ table_column :created_at
221
+
222
+ # If the name of the table column matches a belongs_to in our collection's main class
223
+ # This column will be detected as a belongs_to and some predefined filters will be set up
224
+ # So declaring the following
225
+ table_column :user
226
+
227
+ # Will have the same behaviour as declaring
228
+ table_column :user_id, :if => Proc.new { attributes[:user_id].blank? }, :filter => {:type => :select, :values => Proc.new { User.all.map { |user| [user.id, user.to_s] }.sort { |x, y| x[1] <=> y[1] } } } do |post|
229
+ post.user.to_s
230
+ end
231
+ ```
232
+
233
+ All table_columns are `:visible => true`, `:sortable => true` by default.
234
+
235
+ ### General Options
236
+
237
+ The following options control the general behaviour of the column:
238
+
239
+ ```ruby
240
+ :column => 'users.id' # Set this if you're doing something tricky with the database. Used internally for .order() and .where() clauses
241
+ :type => :string # Derived from the ActiveRecord attribute default datatype. Controls searching behaviour. Valid options include :string, :text, :datetime, :integer, :boolean, :year
242
+ :if => Proc.new { attributes[:user_id].blank? } # Excludes this table_column entirely if false. See "Initialize with attributes" section of this README below
243
+ ```
244
+
245
+ ### Display Options
246
+
247
+ The following options control the display behaviour of the column:
248
+
249
+ ```ruby
250
+ :label => 'Nice Label' # Override the default column header label
251
+ :sortable => true|false # Allow sorting of this column. Otherwise the up/down arrows on the frontend will be disabled.
252
+ :visible => true|false # Hide this column at startup. Column visbility can be changed on the frontend. By default, hidden column filter terms are ignored.
253
+ :width => '100%'|'100px' # Set the width of this column. Can be set on one, all or some of the columns. If using percentages, should never add upto more than 100%
254
+ ```
255
+
256
+ ### Filtering Options
257
+
258
+ Setting a filter will create an appropriate text/number/select input in the header row of the column.
259
+
260
+ The following options control the filtering behaviour of the column:
261
+
262
+ ```ruby
263
+ table_column :created_at, :filter => false # Disable filtering on this column entirely
264
+ table_column :created_at, :filter => {...} # Enable filtering with these options
265
+
266
+ :filter => {:type => :number}
267
+ :filter => {:type => :text}
268
+
269
+ :filter => {:type => :select, :values => ['One', 'Two'], :selected => 'Two'}
270
+ :filter => {:type => :select, :values => [*2010..(Time.zone.now.year+6)]}
271
+ :filter => {:type => :select, :values => Proc.new { PostCategory.all } }
272
+ :filter => {:type => :select, :values => Proc.new { User.all.order(:email).map { |obj| [obj.id, obj.email] } } }
273
+ ```
274
+
275
+ Some additional, lesser used options include:
276
+
277
+ ```ruby
278
+ :filter => {:when_hidden => true} # By default a hidden column's search filter will be ignored, unless this is true. Can be used for scoping.
279
+ :filter => {:fuzzy => true} # Will use an ILIKE/includes rather than = when filtering. Use this for selects.
280
+ ```
281
+
282
+ ### Rendering Options
283
+
284
+ There are a few different ways to render each column's output.
285
+
286
+ Any standard view helpers like `link_to` or `simple_format` and any custom helpers available to your views will be available.
287
+
288
+ All of the following rendering options can be used interchangeably:
289
+
290
+ Block format (really, this is your cleanest option):
291
+
292
+ ```ruby
293
+ table_column :created_at do |post|
294
+ if post.created_at > (Time.zone.now-1.year)
295
+ link_to('this year', post_path(post))
296
+ else
297
+ link_to(post.created_at.strftime("%Y-%m-%d %H:%M:%S"), post_path(post))
298
+ end
299
+ end
300
+ ```
301
+
302
+ Proc format:
303
+
304
+ ```ruby
305
+ table_column :created_at, :proc => Proc.new { |post| link_to(post.created_at, post_path(post)) }
306
+ ```
307
+
308
+ Partial format:
309
+
310
+ ```ruby
311
+ table_column :actions, :partial => '/posts/actions' # render this partial for each row of the table
312
+ ```
313
+
314
+ then in your `/app/views/posts/_actions.html.erb` file:
315
+
316
+ ```erb
317
+ <p><%= link_to('View', post_path(post)) %></p>
318
+ <p><%= link_to('Edit', edit_post_path(post)) %></p>
319
+ ```
320
+
321
+ The local object name will either match the database table singular name `post`, the name of the partial `actions`, or `obj` unless overridden with:
322
+
323
+ ```ruby
324
+ table_column :actions, :partial => '/posts/actions', :partial_local => 'the_post'
325
+ ```
326
+
327
+ There are also a built in helper, `datatables_admin_path?` to considering if the current screen is in the `/admin` namespace:
328
+
329
+ ```ruby
330
+ table_column :created_at do |post|
331
+ if datatables_admin_path?
332
+ link_to admin_posts_path(post)
333
+ else
334
+ link_to posts_path(post)
335
+ end
336
+ end
337
+ ```
338
+
339
+ The request object is available to the table_column, so you could just as easily call:
340
+
341
+ ```ruby
342
+ request.referer.include?('/admin/')
343
+ ```
344
+
345
+
346
+ ## table_columns
347
+
348
+ Quickly create multiple table_columns all with default options:
349
+
350
+ ```ruby
351
+ table_columns :id, :created_at, :updated_at, :category, :title
352
+ ```
353
+
354
+ ## array_column
355
+
356
+ `array_column` accepts the same options as `table_column` and behaves identically on the frontend.
357
+
358
+ The difference occurs with sorting and filtering:
359
+
360
+ With a `table_column`, the frontend sends some search terms to the server, the raw database table is searched & sorted using standard ActiveRecord .where(), the appropriate rows returned, and then each row is rendered as per the rendering options.
361
+
362
+ With an `array_column`, the front end sends some search terms to the server, all rows are returned and rendered, and then the rendered output is searched & sorted.
363
+
364
+ This allows the output of an `array_column` to be anything complex that cannot be easily computed from the database.
365
+
366
+ When searching & sorting with a mix of table_columns and array_columns, all the table_columns are processed first so the most work is put on the database, the least on rails.
367
+
368
+
369
+ ## default_order
370
+
371
+ Sort the table by this field and direction on start up
372
+
373
+ ```ruby
374
+ default_order :created_at, :asc|:desc
375
+ ```
376
+
377
+ ## Additional Functionality
378
+
379
+ There are a few other ways to customize the behaviour of effective_datatables
380
+
381
+ ### Customize Filter Behaviour
382
+
383
+ This gem does its best to provide "just works" filtering of both raw SQL (table_column) and processed results (array_column) out-of-the-box.
384
+
385
+ It's also very easy to override the filter behaviour on a per-column basis.
386
+
387
+ Keep in mind, columns that are hidden will not be considered by the filter results unless `:filter => {:when_hidden => true}` is passed to table_column
388
+
389
+ For custom filter behaviour, specify a `def search_column` method in the datatables model file:
390
+
391
+ ```ruby
392
+ def collection
393
+ User.unscoped.uniq
394
+ .joins('LEFT JOIN customers ON customers.user_id = users.id')
395
+ .select('users.*')
396
+ .select('customers.stripe_customer_id AS stripe_customer_id')
397
+ .includes(:addresses)
398
+ end
399
+
400
+ def search_column(collection, table_column, search_term)
401
+ if table_column[:name] == 'subscription_types'
402
+ collection.where('subscriptions.stripe_plan_id ILIKE ?', "%#{search_term}%")
403
+ else
404
+ super
405
+ end
406
+ end
407
+ ```
408
+
409
+ ### Initialize with attributes
410
+
411
+ Any attributes passed to `.new()` will be persisted through the lifecycle of the datatable.
412
+
413
+ You can use this to scope the datatable collection or create even more advanced search behaviour.
414
+
415
+ In the following example we will hide the User column and scope the collection to a specific user.
416
+
417
+ In your controller:
418
+
419
+ ```ruby
420
+ class PostsController < ApplicationController
421
+ def index
422
+ @datatable = Effective::Datatables::Posts.new(:user_id => current_user.try(:id))
423
+ end
424
+ end
425
+ ```
426
+
427
+ Scope the query to the passed user in in your collection method:
428
+
429
+ ```ruby
430
+ def collection
431
+ if attributes[:user_id]
432
+ Post.where(:user_id => attributes[:user_id])
433
+ else
434
+ Post.all
435
+ end
436
+ end
437
+ ```
438
+
439
+ and remove the table_column when a user_id is present:
440
+
441
+ ```ruby
442
+ table_column :user_id, :if => Proc.new { attributes[:user_id].blank? } do |post|
443
+ post.user.email
444
+ end
445
+ ```
446
+
447
+ ## Array Backed collection
448
+
449
+ Don't want to use ActiveRecord? Not a problem.
450
+
451
+ Define your collection as an Array of Arrays, declare only array_columns, and everything works as expected.
452
+
453
+ ```ruby
454
+ module Effective
455
+ module Datatables
456
+ class ArrayBackedDataTable < Effective::Datatable
457
+ array_column :id
458
+ array_column :first_name
459
+ array_column :last_name
460
+ array_column :email
461
+
462
+ def collection
463
+ [
464
+ [1, 'Matthew', 'Riemer', 'matthew@agilestyle.com'],
465
+ [2, 'Dallas', 'Meidinger', 'dallas@agilestyle.com'],
466
+ [3, 'Warren', 'Uhrich', 'warren@agilestyle.com'],
467
+ [4, 'Stephen', 'Brown', 'stephen@agilestyle.com'],
468
+ [5, 'Dana', 'Janssen', 'dana@agilestyle.com'],
469
+ [6, 'Ashley', 'Janssen', 'ashley@agilestyle.com'],
470
+ ]
471
+ end
472
+
473
+ end
474
+ end
475
+ end
476
+ ```
477
+
478
+ ## Get access to the raw results
479
+
480
+ After all the searching, sorting and rendering of final results is complete, the server sends back an Array of Arrays to the front end jQuery DataTable
481
+
482
+ The finalize method provides a hook to process the final collection as an Array of Arrays just before it is convered to JSON.
483
+
484
+ This final collection is available after searching, sorting and pagination.
485
+
486
+ As you have full control over the table_column presentation, I can't think of any reason you would actually need or want this:
487
+
488
+ ```ruby
489
+ def finalize(collection)
490
+ collection.each do |row|
491
+ row.each do |column|
492
+ column.gsub!('horse', 'force') if column.kind_of?(String)
493
+ end
494
+ end
495
+ end
496
+ ```
497
+
498
+ ## Authorization
499
+
500
+ All authorization checks are handled via the config.authorization_method found in the `config/initializers/effective_datatables.rb` file.
501
+
502
+ It is intended for flow through to CanCan or Pundit, but neither of those gems are required.
503
+
504
+ This method is called by the controller action with the appropriate action and resource
505
+
506
+ Action will be `:index`
507
+
508
+ The resource will be the collection base class, such as `Post`. This can be overridden:
509
+
510
+ ```ruby
511
+ def collection_class
512
+ NotPost
513
+ end
514
+ ```
515
+
516
+ The authorization method is defined in the initializer file:
517
+
518
+ ```ruby
519
+ # As a Proc (with CanCan)
520
+ config.authorization_method = Proc.new { |controller, action, resource| authorize!(action, resource) }
521
+ ```
522
+
523
+ ```ruby
524
+ # As a Custom Method
525
+ config.authorization_method = :my_authorization_method
526
+ ```
527
+
528
+ and then in your application_controller.rb:
529
+
530
+ ```ruby
531
+ def my_authorization_method(action, resource)
532
+ current_user.is?(:admin) || EffectivePunditPolicy.new(current_user, resource).send('#{action}?')
533
+ end
534
+ ```
535
+
536
+ or disabled entirely:
537
+
538
+ ```ruby
539
+ config.authorization_method = false
540
+ ```
541
+
542
+ If the method or proc returns false (user is not authorized) an `Effective::AccessDenied` exception will be raised
543
+
544
+ You can rescue from this exception by adding the following to your application_controller.rb:
545
+
546
+ ```ruby
547
+ rescue_from Effective::AccessDenied do |exception|
548
+ respond_to do |format|
549
+ format.html { render 'static_pages/access_denied', :status => 403 }
550
+ format.any { render :text => 'Access Denied', :status => 403 }
551
+ end
552
+ end
553
+ ```
554
+
555
+
556
+ ## License
557
+
558
+ MIT License. Copyright [Code and Effect Inc.](http://www.codeandeffect.com/)
559
+
560
+ Code and Effect is the product arm of [AgileStyle](http://www.agilestyle.com/), an Edmonton-based shop that specializes in building custom web applications with Ruby on Rails.
561
+
562
+
563
+ ## Testing
564
+
565
+ The test suite for this gem is unfortunately not yet complete.
566
+
567
+ Run tests by:
568
+
569
+ ```ruby
570
+ rake spec
571
+ ```
572
+
573
+ ## Contributing
574
+
575
+ 1. Fork it
576
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
577
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
578
+ 4. Push to the branch (`git push origin my-new-feature`)
579
+ 5. Bonus points for test coverage
580
+ 6. Create new Pull Request
581
+