flexirails 0.1.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 (101) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +20 -0
  3. data/README.md +171 -0
  4. data/Rakefile +39 -0
  5. data/app/assets/stylesheets/flexirails.scss +55 -0
  6. data/app/helpers/flexirails_helper.rb +25 -0
  7. data/app/models/flexirails/array_view.rb +17 -0
  8. data/app/models/flexirails/view.rb +123 -0
  9. data/app/views/flexirails/_container.html.erb +28 -0
  10. data/app/views/flexirails/_navigation.html.erb +66 -0
  11. data/lib/flexirails.rb +5 -0
  12. data/lib/flexirails/engine.rb +4 -0
  13. data/lib/flexirails/version.rb +3 -0
  14. data/test/dummy/Rakefile +7 -0
  15. data/test/dummy/app/assets/javascripts/application.js +9 -0
  16. data/test/dummy/app/assets/stylesheets/application.scss +7 -0
  17. data/test/dummy/app/controllers/active_record_controller.rb +70 -0
  18. data/test/dummy/app/controllers/application_controller.rb +3 -0
  19. data/test/dummy/app/controllers/static_controller.rb +68 -0
  20. data/test/dummy/app/helpers/application_helper.rb +2 -0
  21. data/test/dummy/app/models/active_record_view.rb +23 -0
  22. data/test/dummy/app/models/person.rb +2 -0
  23. data/test/dummy/app/models/static.rb +5 -0
  24. data/test/dummy/app/models/static_view.rb +5 -0
  25. data/test/dummy/app/views/active_record/index.html.erb +7 -0
  26. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  27. data/test/dummy/app/views/static/index.html.erb +7 -0
  28. data/test/dummy/config.ru +4 -0
  29. data/test/dummy/config/application.rb +44 -0
  30. data/test/dummy/config/boot.rb +10 -0
  31. data/test/dummy/config/database.yml +25 -0
  32. data/test/dummy/config/environment.rb +5 -0
  33. data/test/dummy/config/environments/development.rb +30 -0
  34. data/test/dummy/config/environments/production.rb +60 -0
  35. data/test/dummy/config/environments/test.rb +42 -0
  36. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  37. data/test/dummy/config/initializers/inflections.rb +10 -0
  38. data/test/dummy/config/initializers/mime_types.rb +5 -0
  39. data/test/dummy/config/initializers/secret_token.rb +8 -0
  40. data/test/dummy/config/initializers/session_store.rb +8 -0
  41. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  42. data/test/dummy/config/locales/de.yml +8 -0
  43. data/test/dummy/config/locales/en.yml +8 -0
  44. data/test/dummy/config/routes.rb +60 -0
  45. data/test/dummy/db/development.sqlite3 +0 -0
  46. data/test/dummy/db/migrate/20131109204431_create_people.rb +9 -0
  47. data/test/dummy/db/schema.rb +23 -0
  48. data/test/dummy/db/test.sqlite3 +0 -0
  49. data/test/dummy/log/development.log +5482 -0
  50. data/test/dummy/log/test.log +4932 -0
  51. data/test/dummy/public/404.html +26 -0
  52. data/test/dummy/public/422.html +26 -0
  53. data/test/dummy/public/500.html +26 -0
  54. data/test/dummy/public/favicon.ico +0 -0
  55. data/test/dummy/script/rails +6 -0
  56. data/test/dummy/tmp/cache/assets/development/sass/62614c0f166e45da36cfbb2781f9667e47799670/application.scssc +0 -0
  57. data/test/dummy/tmp/cache/assets/development/sass/9178b5a65ff97d4c91c8e2380e5ac8d8eb939b91/flexirails.scssc +0 -0
  58. data/test/dummy/tmp/cache/assets/development/sass/b2a814b45c3cca5078e8af8655d3f89a5f705998/flexirails.scssc +0 -0
  59. data/test/dummy/tmp/cache/assets/development/sass/e91bee6f7bc4c18550721ba1f2d7361da7e3d2e5/application.scssc +0 -0
  60. data/test/dummy/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  61. data/test/dummy/tmp/cache/assets/development/sprockets/24585794383ac6ae2640d6c9e4affdbd +0 -0
  62. data/test/dummy/tmp/cache/assets/development/sprockets/2edad7c2ee0e34d5988da78ef799ca6c +0 -0
  63. data/test/dummy/tmp/cache/assets/development/sprockets/2ef811475ef30c8afbab72317974e714 +0 -0
  64. data/test/dummy/tmp/cache/assets/development/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  65. data/test/dummy/tmp/cache/assets/development/sprockets/33fea692ac14771a738e10ee5d76ae96 +0 -0
  66. data/test/dummy/tmp/cache/assets/development/sprockets/352bab412d75fa19d0a07504553b59df +0 -0
  67. data/test/dummy/tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  68. data/test/dummy/tmp/cache/assets/development/sprockets/5584751febc87e8b2ba4b7f38285eceb +0 -0
  69. data/test/dummy/tmp/cache/assets/development/sprockets/69e627a9d109212088a08e7938543d9d +0 -0
  70. data/test/dummy/tmp/cache/assets/development/sprockets/6e1bd95023705b5529e7ccc754a02867 +0 -0
  71. data/test/dummy/tmp/cache/assets/development/sprockets/836b5f0381caa8a96cebbee674df2708 +0 -0
  72. data/test/dummy/tmp/cache/assets/development/sprockets/85c3b8d54510866ae2cc33aedc247eb0 +0 -0
  73. data/test/dummy/tmp/cache/assets/development/sprockets/889b9afc807369ef171867cb782dd99c +0 -0
  74. data/test/dummy/tmp/cache/assets/development/sprockets/92613a75279536c4bcf4f3ba6cfde494 +0 -0
  75. data/test/dummy/tmp/cache/assets/development/sprockets/c0f4ca569d58f951461e6ccadfdd2649 +0 -0
  76. data/test/dummy/tmp/cache/assets/development/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  77. data/test/dummy/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  78. data/test/dummy/tmp/cache/assets/development/sprockets/dcea77c9b7315ca8f48eb8357e38a219 +0 -0
  79. data/test/dummy/tmp/cache/assets/development/sprockets/e714eeaf481f5a44ddca306c4a9c7137 +0 -0
  80. data/test/dummy/tmp/cache/assets/development/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  81. data/test/dummy/tmp/cache/assets/test/sass/9178b5a65ff97d4c91c8e2380e5ac8d8eb939b91/flexirails.scssc +0 -0
  82. data/test/dummy/tmp/cache/assets/test/sass/e91bee6f7bc4c18550721ba1f2d7361da7e3d2e5/application.scssc +0 -0
  83. data/test/dummy/tmp/cache/assets/test/sprockets/2ef811475ef30c8afbab72317974e714 +0 -0
  84. data/test/dummy/tmp/cache/assets/test/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  85. data/test/dummy/tmp/cache/assets/test/sprockets/352bab412d75fa19d0a07504553b59df +0 -0
  86. data/test/dummy/tmp/cache/assets/test/sprockets/5584751febc87e8b2ba4b7f38285eceb +0 -0
  87. data/test/dummy/tmp/cache/assets/test/sprockets/6e1bd95023705b5529e7ccc754a02867 +0 -0
  88. data/test/dummy/tmp/cache/assets/test/sprockets/836b5f0381caa8a96cebbee674df2708 +0 -0
  89. data/test/dummy/tmp/cache/assets/test/sprockets/85c3b8d54510866ae2cc33aedc247eb0 +0 -0
  90. data/test/dummy/tmp/cache/assets/test/sprockets/889b9afc807369ef171867cb782dd99c +0 -0
  91. data/test/dummy/tmp/cache/assets/test/sprockets/92613a75279536c4bcf4f3ba6cfde494 +0 -0
  92. data/test/dummy/tmp/cache/assets/test/sprockets/c0f4ca569d58f951461e6ccadfdd2649 +0 -0
  93. data/test/dummy/tmp/cache/assets/test/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  94. data/test/dummy/tmp/cache/assets/test/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  95. data/test/dummy/tmp/pids/server.pid +1 -0
  96. data/test/models/flexirails/array_view_test.rb +44 -0
  97. data/test/models/flexirails/view_test.rb +46 -0
  98. data/test/rails-localization-engine_test.rb +7 -0
  99. data/test/test_helper.rb +14 -0
  100. data/test/views/flexirails/navigation_test.rb +65 -0
  101. metadata +306 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 13cd7f185547a32a1c78255b13533dde98c348a2
4
+ data.tar.gz: 7566fb2bb29edaf12737db45c5e6c71aeee5df50
5
+ SHA512:
6
+ metadata.gz: 7168c88257719d55a31be8bd847f12872ab6d4b98de945e789669e1c0a1907cc927209508c2633ba9f09e2f49415f68c21a9529504f48a3817448018bed2b284
7
+ data.tar.gz: 4e597fe640fbe4c06db3502114f54921375ba73dba8e7dfbb84ead2b789256e94e91bb631122e048a03e5137c0675454b876137beb9b94afadb9b480e6c3541b
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2011-2013 Raphael Randschau (nicolai86@me.com)
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,171 @@
1
+ # Flexirails
2
+
3
+ ORM independent table view for Ruby on Rails.
4
+ Has support for partial rendering, turbolinks and i18n as well as basic sorting and filtering facilities.
5
+ If you want more abstraction you need to build it yourself.
6
+
7
+ Look at the bright side: want to use bananadb? Go ahead.<br>
8
+ Just wrote your self CSV-In-Memory-DB? No Problem.<br>
9
+ Reading each row from /dev/null. Sure, why not?
10
+
11
+ You are in control. Just need to know how!
12
+
13
+ ### Installation
14
+
15
+ Add `gem "flexirails"` to your `Gemfile`.
16
+
17
+ ### Usage
18
+
19
+ Now you need two more steps to get going:
20
+
21
+ 1. subclass `::Flexirails::View` or `::Flexirails::ArrayView`.
22
+
23
+ ``` ruby
24
+ class PeopleView < ::Flexirails::View
25
+ def total
26
+ Person.count
27
+ end
28
+
29
+ def query offset, limit
30
+ Person.offset(offset).limit(limit)
31
+ end
32
+
33
+ def columns
34
+ %w(id name)
35
+ end
36
+ end
37
+ ```
38
+
39
+ 2. instanciate your view class in your controller:
40
+
41
+ ``` ruby
42
+ class PeopleController < ApplicationController
43
+ protected
44
+ def people_view
45
+ @people_view ||= PeopleView.new(params)
46
+ end
47
+ helper_method :people_view
48
+ end
49
+ ```
50
+
51
+ 3. render appropriate partials in your views:
52
+
53
+ ``` erb
54
+ <%= render :partial => '/flexirails/navigation', :locals => { :view => people_view } %>
55
+ <%= render_flexirails_view(people_view, { :class => 'statics' }) %>
56
+ ```
57
+
58
+ Columns are translated as `<lang>.<view_as_snake_case>.<column>`, e.g. `de.people_view.name`.
59
+
60
+ ### Advanced Usage
61
+
62
+ You can pass additional informations to your view - e.g. the current user for complex logic
63
+
64
+ ``` ruby
65
+ class PeopleView < ::Flexirails::View
66
+ attr_reader :current_user, :current_project
67
+ def initialize params, user, project
68
+ @current_user = user
69
+ @current_project = project
70
+ super params
71
+ end
72
+
73
+ def scoped
74
+ if current_user.admin?
75
+ Person.scoped
76
+ else
77
+ current_project.people
78
+ end
79
+ end
80
+
81
+ def total
82
+ scoped.count
83
+ end
84
+
85
+ def query offset, limit
86
+ scoped.offset(offset).limit(limit)
87
+ end
88
+ end
89
+ ```
90
+
91
+ By default attributes are extracted from the current row object. But you can render partials if you want to:
92
+ ``` ruby
93
+ class PeopleView < ::Flexirails::View
94
+ def total
95
+ Person.count
96
+ end
97
+
98
+ def query offset, limit
99
+ Person.offset(offset).limit(limit)
100
+ end
101
+
102
+ def columns
103
+ %w(id name actions)
104
+ end
105
+
106
+ def render_actions person, context
107
+ context.render :partial => "actions", :locals => { :person => person }
108
+ end
109
+ end
110
+ ```
111
+
112
+ You can sort your data if you want to. `order` and `direction` are sanitized by default, no need to check.
113
+ ``` ruby
114
+ class PeopleView < ::Flexirails::View
115
+ def query offset, limit
116
+ scope = if order_query?
117
+ Person.order("#{order} #{direction}")
118
+ else
119
+ Person
120
+ end
121
+ scope.offset(offset).limit(limit)
122
+ end
123
+
124
+ def sortable_columns
125
+ %w(id)
126
+ end
127
+ end
128
+ ```
129
+
130
+ You can filter your data if you want to:
131
+ ``` ruby
132
+ class PeopleView < ::Flexirails::View
133
+ attr_reader :minimum_id
134
+ def initialize params
135
+ @minimum_id = params.fetch(:minimum_id, nil)
136
+
137
+ super params
138
+ end
139
+
140
+ def scoped
141
+ if minimum_id.present?
142
+ Person.where(["id > ?", minimum_id])
143
+ else
144
+ Person.scoped
145
+ end
146
+ end
147
+
148
+ def total
149
+ scoped.count
150
+ end
151
+
152
+ def query offset, limit
153
+ scoped.offset(offset).limit(limit)
154
+ end
155
+ end
156
+ ```
157
+
158
+ ### TODO
159
+
160
+ - enhance the test suite
161
+ - refactor the small, inlined- js a little. its ugly as hell
162
+ - refactor the css. its ugly as hell as well
163
+ - maybe add a small abstraction for ActiveRecord Views
164
+
165
+ ### Contributing
166
+
167
+ 1. Fork it
168
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
169
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
170
+ 4. Push to the branch (`git push origin my-new-feature`)
171
+ 5. Create new Pull Request
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ require "bundler/gem_tasks"
5
+ rescue LoadError
6
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
7
+ end
8
+
9
+ begin
10
+ require 'rdoc/task'
11
+ rescue LoadError
12
+ require 'rdoc/rdoc'
13
+ require 'rake/rdoctask'
14
+ RDoc::Task = Rake::RDocTask
15
+ end
16
+
17
+ RDoc::Task.new(:rdoc) do |rdoc|
18
+ rdoc.rdoc_dir = 'rdoc'
19
+ rdoc.title = 'Flexirails'
20
+ rdoc.options << '--line-numbers'
21
+ rdoc.rdoc_files.include('README.rdoc')
22
+ rdoc.rdoc_files.include('lib/**/*.rb')
23
+ end
24
+
25
+
26
+
27
+ Bundler::GemHelper.install_tasks
28
+
29
+ require 'rake/testtask'
30
+
31
+ Rake::TestTask.new(:test) do |t|
32
+ t.libs << 'lib'
33
+ t.libs << 'test'
34
+ t.pattern = 'test/**/*_test.rb'
35
+ t.verbose = false
36
+ end
37
+
38
+
39
+ task :default => :test
@@ -0,0 +1,55 @@
1
+ .filter {
2
+ .row .columns {
3
+ height: 32px !important;
4
+ line-height: 32px !important;
5
+ margin-bottom: 3px;
6
+ }
7
+ margin-bottom: 5px;
8
+ }
9
+
10
+ div.flexirails {
11
+ overflow: scroll;
12
+ }
13
+
14
+ nav.flexirails {
15
+ div {
16
+ display: inline-block;
17
+ }
18
+ input {
19
+ display: inline-block;
20
+ }
21
+ .page {
22
+ input {
23
+ width: 50px;
24
+ }
25
+ }
26
+ svg {
27
+ fill: white;
28
+ }
29
+ .pagination a {
30
+ height: 32px;
31
+ line-height: 34px;
32
+ display: inline-block;
33
+ vertical-align: middle;
34
+ }
35
+ }
36
+
37
+ .flexirails table {
38
+ width: 100%;
39
+ th {
40
+ text-align: left;
41
+ }
42
+ td {
43
+ padding: 5px;
44
+ }
45
+ td.actions {
46
+ span {
47
+ display: inline-block;
48
+ }
49
+
50
+ a {
51
+ min-width: 32px;
52
+ min-height: 32px;
53
+ }
54
+ }
55
+ }
@@ -0,0 +1,25 @@
1
+ require 'url_plumber'
2
+
3
+ module FlexirailsHelper
4
+ def pagination_first_icon
5
+ return '<svg version="1.2" baseProfile="tiny" id="Navigation_first" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="16px" height="16px" viewBox="0 0 512 512" overflow="inherit" xml:space="preserve"> <path d="M186.178,256.243l211.583,166.934V89.312L186.178,256.243z M112.352,422.512h66.179V89.975h-66.179V422.512z"/> </svg>'
6
+ end
7
+ def pagination_prev_icon
8
+ return '<svg version="1.2" baseProfile="tiny" id="Navigation_left" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="16px" height="16px" viewBox="0 0 512 512" overflow="inherit" xml:space="preserve"> <polygon points="148.584,255.516 360.168,88.583 360.166,422.445 "/> </svg>'
9
+ end
10
+ def pagination_last_icon
11
+ return '<svg version="1.2" baseProfile="tiny" id="Navigation_last" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="16px" height="16px" viewBox="0 0 512 512" overflow="inherit" xml:space="preserve"> <path d="M111.708,424.514l211.581-166.927L111.708,90.654V424.514z M330.935,87.311v332.544h66.173V87.311H330.935z"/> </svg>'
12
+ end
13
+ def pagination_next_icon
14
+ return '<svg version="1.2" baseProfile="tiny" id="Navigation_right" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="16px" height="16px" viewBox="0 0 512 512" overflow="inherit" xml:space="preserve"> <polygon points="360.124,255.513 148.535,422.442 148.537,88.58 "/> </svg>'
15
+ end
16
+ def render_flexirails_view view, opts = {}
17
+ return render partial: '/flexirails/container', locals: { view: view, table_class: opts.fetch(:class) { "" } }
18
+ end
19
+ def url_plumb(key, value)
20
+ url_for(::UrlPlumber::Plumber.new(params).plumb(key => value))
21
+ end
22
+ def url_batch_plumb(hash)
23
+ url_for(::UrlPlumber::Plumber.new(params).plumb(hash))
24
+ end
25
+ end
@@ -0,0 +1,17 @@
1
+ module Flexirails
2
+ class ArrayView < ::Flexirails::View
3
+ attr_reader :items
4
+ def initialize params, items
5
+ @items = items
6
+ super params
7
+ end
8
+
9
+ def query offset, limit
10
+ items[offset..(offset+limit-1)]
11
+ end
12
+
13
+ def total
14
+ items.size
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,123 @@
1
+ module Flexirails
2
+ class View
3
+ attr_reader :offset, :limit, :current_page, :per_page, :order, :direction, :params
4
+
5
+ def initialize params
6
+ @params = params
7
+ pagination = params.fetch(:pagination) { params || Hash.new }
8
+
9
+ @current_page = pagination.fetch(:current_page) { 1 }.to_i
10
+ @per_page = pagination.fetch(:per_page) { 25 }.to_i
11
+ @order = sanitize(pagination.fetch(:order) { nil })
12
+ @direction = sanitize_direction(pagination.fetch(:direction) { nil })
13
+
14
+ if @current_page > total_page_count
15
+ @current_page = 1
16
+ end
17
+
18
+ @offset = (current_page-1) * per_page
19
+ @limit = per_page
20
+ end
21
+
22
+ def next_pagination_direction column
23
+ if order == column
24
+ if direction == "DESC"
25
+ nil
26
+ else
27
+ if direction == nil
28
+ "ASC"
29
+ else
30
+ "DESC"
31
+ end
32
+ end
33
+ else
34
+ "ASC"
35
+ end
36
+ end
37
+
38
+ def total_page_count
39
+ return (self.total.to_f / self.per_page.to_f).ceil
40
+ end
41
+
42
+ def total
43
+ raise "ImplementationMissing"
44
+ end
45
+
46
+ def query offset = self.offset, limit = self.limit
47
+ raise "ImplementationMissing"
48
+ end
49
+
50
+ def has_prev_path
51
+ return self.current_page > 1
52
+ end
53
+ def has_next_path
54
+ return self.current_page < total_page_count
55
+ end
56
+
57
+ def sortable_columns
58
+ return %w()
59
+ end
60
+
61
+ def columns
62
+ sortable_columns
63
+ end
64
+
65
+ def order_query?
66
+ return order.present? && direction.present?
67
+ end
68
+ alias_method :order_results?, :order_query?
69
+
70
+ def rows
71
+ return @rows ||= query(offset, limit)
72
+ end
73
+
74
+ def i18n_scope clazz = self.class
75
+ return clazz.name.tableize.singularize.gsub('/','.')
76
+ end
77
+
78
+ def i18n_default name
79
+ scopes = []
80
+ clazz = self.class
81
+ clazz.ancestors.each do |ancestor|
82
+ break if ancestor == Object
83
+ scopes << [i18n_scope(ancestor),name].compact.join('.').to_sym
84
+ end
85
+ return scopes
86
+ end
87
+
88
+ def t name, args = {}
89
+ I18n.t([i18n_scope,name].compact.join('.'), { default: i18n_default(name) }.merge(args))
90
+ end
91
+
92
+ def render_column column, row, context
93
+ method_to_call = "render_#{column.gsub(/\./, '_')}"
94
+ if self.respond_to?(method_to_call.to_sym)
95
+ return self.send method_to_call.to_sym, row, context
96
+ else
97
+ parts = column.split('.').map(&:to_sym)
98
+ object = row
99
+ parts.each do |part|
100
+ object = object.send(part)
101
+ end
102
+ return object
103
+ end
104
+ end
105
+
106
+ def pagination_hash
107
+ return {
108
+ current_page: self.current_page,
109
+ per_page: self.per_page,
110
+ order: self.order,
111
+ direction: self.direction
112
+ }
113
+ end
114
+
115
+ private
116
+ def sanitize_direction direction
117
+ return %w(ASC DESC).include?(direction) ? direction : nil
118
+ end
119
+ def sanitize attribute
120
+ return columns.include?(attribute) ? attribute : nil
121
+ end
122
+ end
123
+ end