effective_datatables 2.12.2 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +632 -512
  3. data/app/assets/javascripts/dataTables/buttons/buttons.html5.js +176 -177
  4. data/app/assets/javascripts/dataTables/buttons/buttons.print.js +2 -0
  5. data/app/assets/javascripts/dataTables/buttons/dataTables.buttons.js +14 -14
  6. data/app/assets/javascripts/dataTables/dataTables.bootstrap.js +1 -1
  7. data/app/assets/javascripts/dataTables/jquery.dataTables.js +246 -217
  8. data/app/assets/javascripts/effective_datatables.js +2 -3
  9. data/app/assets/javascripts/effective_datatables/events.js.coffee +7 -0
  10. data/app/assets/javascripts/effective_datatables/filters.js.coffee +6 -0
  11. data/app/assets/javascripts/effective_datatables/initialize.js.coffee +42 -39
  12. data/app/assets/javascripts/effective_datatables/reset.js.coffee +7 -0
  13. data/app/assets/javascripts/vendor/jquery.delayedChange.js +1 -1
  14. data/app/assets/stylesheets/dataTables/dataTables.bootstrap.css +0 -1
  15. data/app/assets/stylesheets/effective_datatables.scss +1 -2
  16. data/app/assets/stylesheets/effective_datatables/{_scopes.scss → _filters.scss} +1 -1
  17. data/app/assets/stylesheets/effective_datatables/_overrides.scss +1 -1
  18. data/app/controllers/effective/datatables_controller.rb +2 -4
  19. data/app/helpers/effective_datatables_helper.rb +56 -91
  20. data/app/helpers/effective_datatables_private_helper.rb +55 -64
  21. data/app/models/effective/datatable.rb +103 -177
  22. data/app/models/effective/datatable_column.rb +28 -0
  23. data/app/models/effective/datatable_column_tool.rb +110 -0
  24. data/app/models/effective/datatable_dsl_tool.rb +28 -0
  25. data/app/models/effective/datatable_value_tool.rb +142 -0
  26. data/app/models/effective/effective_datatable/attributes.rb +25 -0
  27. data/app/models/effective/effective_datatable/collection.rb +38 -0
  28. data/app/models/effective/effective_datatable/compute.rb +154 -0
  29. data/app/models/effective/effective_datatable/cookie.rb +29 -0
  30. data/app/models/effective/effective_datatable/dsl.rb +14 -8
  31. data/app/models/effective/effective_datatable/dsl/bulk_actions.rb +5 -6
  32. data/app/models/effective/effective_datatable/dsl/charts.rb +7 -9
  33. data/app/models/effective/effective_datatable/dsl/datatable.rb +107 -57
  34. data/app/models/effective/effective_datatable/dsl/filters.rb +50 -0
  35. data/app/models/effective/effective_datatable/format.rb +157 -0
  36. data/app/models/effective/effective_datatable/hooks.rb +0 -18
  37. data/app/models/effective/effective_datatable/params.rb +34 -0
  38. data/app/models/effective/effective_datatable/resource.rb +108 -0
  39. data/app/models/effective/effective_datatable/state.rb +178 -0
  40. data/app/views/effective/datatables/_actions_column.html.haml +9 -42
  41. data/app/views/effective/datatables/_bulk_actions_column.html.haml +1 -1
  42. data/app/views/effective/datatables/_bulk_actions_dropdown.html.haml +2 -3
  43. data/app/views/effective/datatables/_chart.html.haml +1 -1
  44. data/app/views/effective/datatables/_datatable.html.haml +7 -25
  45. data/app/views/effective/datatables/_filters.html.haml +21 -0
  46. data/app/views/effective/datatables/_reset.html.haml +2 -0
  47. data/app/views/effective/datatables/_resource_column.html.haml +8 -0
  48. data/app/views/effective/datatables/index.html.haml +0 -1
  49. data/config/effective_datatables.rb +9 -32
  50. data/lib/effective_datatables.rb +2 -6
  51. data/lib/effective_datatables/engine.rb +1 -1
  52. data/lib/effective_datatables/version.rb +1 -1
  53. data/lib/generators/effective_datatables/install_generator.rb +2 -2
  54. metadata +39 -19
  55. data/app/assets/javascripts/dataTables/colreorder/dataTables.colReorder.js +0 -27
  56. data/app/assets/javascripts/dataTables/jszip/jszip.js +0 -9155
  57. data/app/assets/javascripts/effective_datatables/scopes.js.coffee +0 -9
  58. data/app/models/effective/active_record_datatable_tool.rb +0 -242
  59. data/app/models/effective/array_datatable_tool.rb +0 -97
  60. data/app/models/effective/effective_datatable/ajax.rb +0 -101
  61. data/app/models/effective/effective_datatable/charts.rb +0 -20
  62. data/app/models/effective/effective_datatable/dsl/scopes.rb +0 -23
  63. data/app/models/effective/effective_datatable/helpers.rb +0 -24
  64. data/app/models/effective/effective_datatable/options.rb +0 -309
  65. data/app/models/effective/effective_datatable/rendering.rb +0 -365
  66. data/app/views/effective/datatables/_scopes.html.haml +0 -21
@@ -0,0 +1,29 @@
1
+ module Effective
2
+ module EffectiveDatatable
3
+ module Cookie
4
+
5
+ def cookie_name
6
+ @cookie_name ||= "datatable-#{URI(datatables_ajax_request? ? view.request.referer : view.request.url).path}-#{to_param}".parameterize
7
+ end
8
+
9
+ private
10
+
11
+ def load_cookie!
12
+ @cookie ||= (
13
+ cookie = view.cookies.signed[cookie_name]
14
+
15
+ if cookie.present?
16
+ data = Marshal.load(Base64.decode64(cookie))
17
+ raise 'invalid cookie' unless [data, data[:attributes], data[:state]].all? { |obj| obj.kind_of?(Hash) }
18
+ data
19
+ end
20
+ )
21
+ end
22
+
23
+ def save_cookie!
24
+ view.cookies.signed[cookie_name] = Base64.encode64(Marshal.dump(attributes: attributes, state: state))
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -1,19 +1,25 @@
1
- # These are Class level methods.
2
-
3
1
  module Effective
4
2
  module EffectiveDatatable
5
3
  module Dsl
6
4
 
7
- def datatable(&block)
8
- define_method('initialize_datatable') { instance_exec(&block) }
5
+ def bulk_actions(&block)
6
+ define_method('initialize_bulk_actions') { dsl_tool.instance_exec(&block) }
9
7
  end
10
8
 
11
- def scopes(&block)
12
- define_method('initialize_scopes') { instance_exec(&block) }
9
+ def charts(&block)
10
+ define_method('initialize_charts') { dsl_tool.instance_exec(&block) }
13
11
  end
14
12
 
15
- def charts(&block)
16
- define_method('initialize_charts') { instance_exec(&block) }
13
+ def collection(&block)
14
+ define_method('initialize_collection') { self._collection = dsl_tool.instance_exec(&block) }
15
+ end
16
+
17
+ def datatable(&block)
18
+ define_method('initialize_datatable') { dsl_tool.instance_exec(&block) }
19
+ end
20
+
21
+ def filters(&block)
22
+ define_method('initialize_filters') { dsl_tool.instance_exec(&block) }
17
23
  end
18
24
 
19
25
  end
@@ -2,22 +2,21 @@ module Effective
2
2
  module EffectiveDatatable
3
3
  module Dsl
4
4
  module BulkActions
5
- # These get added into the view as helpers
6
- # To be called inside datatable { bulk_actions_column do .. end }
5
+
7
6
  def bulk_action(*args)
8
- concat content_tag(:li, link_to(*args))
7
+ datatable._bulk_actions.push(content_tag(:li, link_to(*args)))
9
8
  end
10
9
 
11
10
  def bulk_download(*args)
12
- concat content_tag(:li, link_to(*args), 'data-authenticity-token' => form_authenticity_token)
11
+ datatable._bulk_actions.push(content_tag(:li, link_to(*args), 'data-authenticity-token' => form_authenticity_token))
13
12
  end
14
13
 
15
14
  def bulk_action_divider
16
- concat content_tag(:li, '', class: 'divider', role: 'separator')
15
+ datatable._bulk_actions.push(content_tag(:li, '', class: 'divider', role: 'separator'))
17
16
  end
18
17
 
19
18
  def bulk_action_content(&block)
20
- concat block.call
19
+ datatable._bulk_actions.push(block.call)
21
20
  end
22
21
 
23
22
  end
@@ -3,17 +3,15 @@ module Effective
3
3
  module Dsl
4
4
  module Charts
5
5
  # Instance Methods inside the charts do .. end block
6
- def chart(name, type, options = {}, &block)
6
+ def chart(name, as = 'BarChart', label: nil, legend: true, partial: nil, **options, &compute)
7
+ raise 'expected a block returning an Array of Arrays' unless block_given?
7
8
 
8
- options[:title] ||= (options[:label] || name.to_s.titleize)
9
- options[:legend] = 'none' if options[:legend] == false
10
-
11
- (@charts ||= HashWithIndifferentAccess.new)[name] = {
9
+ datatable._charts[name.to_sym] = {
10
+ as: as,
11
+ compute: compute,
12
12
  name: name,
13
- type: type,
14
- partial: options.delete(:partial),
15
- options: options,
16
- block: (block if block_given?)
13
+ options: { label: (label || name.to_s.titleize), legend: (legend || 'none') }.merge(options),
14
+ partial: partial || '/effective/datatables/chart'
17
15
  }
18
16
  end
19
17
  end
@@ -3,80 +3,130 @@ module Effective
3
3
  module Dsl
4
4
  module Datatable
5
5
  # Instance Methods inside the datatable do .. end block
6
- def default_order(name, direction = :asc)
7
- @default_order = {name => direction}
8
- end
6
+ def order(name, dir = nil)
7
+ raise 'order direction must be :asc or :desc' unless [nil, :asc, :desc].include?(dir)
9
8
 
10
- def default_entries(entries)
11
- @default_entries = entries
9
+ datatable.state[:order_name] ||= name
10
+ datatable.state[:order_dir] ||= dir
12
11
  end
13
12
 
14
- def table_column(name, options = {}, proc = nil, &block)
15
- if block_given?
16
- raise "You cannot use partial: ... with the block syntax" if options[:partial] && !options[:type] == :actions
17
- raise "You cannot use proc: ... with the block syntax" if options[:proc]
18
- options[:block] = block
19
- end
20
- raise "You cannot use both partial: ... and proc: ..." if options[:partial] && options[:proc]
21
-
22
- (@table_columns ||= HashWithIndifferentAccess.new)[name] = options
13
+ def length(length)
14
+ raise 'length must be 10, 25, 50, 100, 250, 1000, :all' unless [10, 25, 50, 100, 250, 1000, :all].include?(length)
15
+ datatable.state[:length] ||= (length == :all ? 9999999 : length)
23
16
  end
24
17
 
25
- def array_column(name, options = {}, proc = nil, &block)
26
- table_column(name, options.merge!(array_column: true), proc, &block)
27
- end
18
+ # A col has its internal values sorted/searched before the block is run
19
+ # Anything done in the block, is purely a format on the after sorted/ordered value
20
+ # the original object == the computed value, which is yielded to the format block
21
+ # You can't do compute with .col
22
+ def col(name, action: nil, as: nil, col_class: nil, label: nil, partial: nil, partial_as: nil, responsive: 10000, search: {}, sort: true, sql_column: nil, th: nil, th_append: nil, visible: true, &format)
23
+ raise 'You cannot use partial: ... with the block syntax' if partial && block_given?
28
24
 
29
- def actions_column(options = {}, proc = nil, &block)
30
- raise 'first parameter to actions_column should be a hash' unless options.kind_of?(Hash)
25
+ datatable._columns[name.to_sym] = Effective::DatatableColumn.new(
26
+ action: action, # resource columns only
27
+ as: as,
28
+ compute: nil,
29
+ col_class: col_class,
30
+ format: (format if block_given?),
31
+ index: datatable.columns.length,
32
+ label: label || name.to_s.titleize,
33
+ name: name.to_sym,
34
+ partial: partial,
35
+ partial_as: partial_as,
36
+ responsive: responsive,
37
+ search: search,
38
+ sort: sort,
39
+ sql_column: sql_column,
40
+ th: th,
41
+ th_append: th_append,
42
+ visible: visible,
43
+ )
44
+ end
31
45
 
32
- show = options.fetch(:show, (EffectiveDatatables.actions_column[:show] rescue false))
33
- edit = options.fetch(:edit, (EffectiveDatatables.actions_column[:edit] rescue false))
34
- destroy = options.fetch(:destroy, (EffectiveDatatables.actions_column[:destroy] rescue false))
35
- unarchive = options.fetch(:unarchive, (EffectiveDatatables.actions_column[:unarchive] rescue false))
36
- name = options.fetch(:name, 'actions')
46
+ # A val is a computed value that is then sorted/searched after the block is run
47
+ # You can have another block by calling .format afterwards to work on the computed value itself
48
+ def val(name, action: nil, as: nil, col_class: nil, label: nil, partial: nil, partial_as: nil, responsive: 10000, search: {}, sort: true, sql_column: nil, th: nil, th_append: nil, visible: true, &compute)
49
+ raise 'You cannot use partial: ... with the block syntax' if partial && block_given?
37
50
 
38
- opts = {
39
- type: :actions,
40
- sortable: false,
41
- filter: false,
42
- responsivePriority: 0,
43
- partial_locals: { show_action: show, edit_action: edit, destroy_action: destroy, unarchive_action: unarchive },
44
- actions_block: block
45
- }.merge(options)
51
+ datatable._columns[name.to_sym] = Effective::DatatableColumn.new(
52
+ action: action, # Resource columns only
53
+ as: as,
54
+ compute: (compute if block_given?),
55
+ col_class: col_class,
56
+ format: nil,
57
+ index: datatable.columns.length,
58
+ label: label || name.to_s.titleize,
59
+ name: name.to_sym,
60
+ partial: partial,
61
+ partial_as: partial_as,
62
+ responsive: responsive,
63
+ search: search,
64
+ sort: sort,
65
+ sql_column: (block_given? ? false : sql_column),
66
+ th: th,
67
+ th_append: th_append,
68
+ visible: visible,
69
+ )
70
+ end
46
71
 
47
- opts[:partial_local] ||= :resource unless opts[:partial].present?
48
- opts[:partial] ||= '/effective/datatables/actions_column' unless proc.present?
72
+ def bulk_actions_col(col_class: nil, partial: nil, partial_as: nil, responsive: 5000)
73
+ raise 'You can only have one bulk actions column' if datatable.columns[:_bulk_actions].present?
49
74
 
50
- table_column(name, opts, proc)
75
+ datatable._columns[:_bulk_actions] = Effective::DatatableColumn.new(
76
+ action: false,
77
+ as: :bulk_actions,
78
+ compute: nil,
79
+ col_class: col_class,
80
+ format: nil,
81
+ index: datatable.columns.length,
82
+ label: '',
83
+ name: :bulk_actions,
84
+ partial: partial || '/effective/datatables/bulk_actions_column',
85
+ partial_as: partial_as,
86
+ responsive: responsive,
87
+ search: { as: :bulk_actions },
88
+ sort: false,
89
+ sql_column: nil,
90
+ th: nil,
91
+ th_append: nil,
92
+ visible: true,
93
+ )
51
94
  end
52
95
 
53
- def bulk_actions_column(options = {}, proc = nil, &block)
54
- raise 'first parameter to bulk_actions_column should be a hash' unless options.kind_of?(Hash)
96
+ def actions_col(show: true, edit: true, destroy: true, col_class: nil, partial: nil, partial_as: nil, responsive: 5000, visible: true, &format)
97
+ raise 'You can only have one actions column' if datatable.columns[:_actions].present?
55
98
 
56
- name = options.fetch(:name, 'bulk_actions')
57
- resource_method = options.fetch(:resource_method, :to_param)
58
-
59
- opts = {
60
- bulk_actions_column: true,
99
+ datatable._columns[:_actions] = Effective::DatatableColumn.new(
100
+ action: false,
101
+ as: :actions,
102
+ compute: nil,
103
+ col_class: col_class,
104
+ format: (format if block_given?),
105
+ index: datatable.columns.length,
61
106
  label: '',
62
- partial_local: :resource,
63
- partial: '/effective/datatables/bulk_actions_column',
64
- partial_locals: { resource_method: resource_method },
65
- sortable: false,
66
- dropdown_partial: '/effective/datatables/bulk_actions_dropdown',
67
- dropdown_block: block
68
- }.merge(options)
107
+ name: :actions,
108
+ partial: partial || '/effective/datatables/actions_column',
109
+ partial_as: partial_as,
110
+ responsive: responsive,
111
+ search: false,
112
+ sort: false,
113
+ sql_column: nil,
114
+ th: nil,
115
+ th_append: nil,
116
+ visible: visible,
69
117
 
70
- table_column(name, opts, proc)
118
+ show: show,
119
+ edit: edit,
120
+ destroy: destroy
121
+ )
71
122
  end
72
123
 
73
- def aggregate(name, options = {}, &block)
74
- if block_given?
75
- raise "You cannot use proc: ... with the block syntax" if options[:proc]
76
- options[:block] = block
77
- end
78
-
79
- (@aggregates ||= HashWithIndifferentAccess.new)[name] = options
124
+ def aggregate(name, label: nil, &compute)
125
+ datatable._aggregates[name.to_sym] = {
126
+ compute: (compute if block_given?),
127
+ label: label || name.to_s.titleize,
128
+ name: name.to_sym,
129
+ }
80
130
  end
81
131
  end
82
132
  end
@@ -0,0 +1,50 @@
1
+ module Effective
2
+ module EffectiveDatatable
3
+ module Dsl
4
+ module Filters
5
+ def filter(name = nil, value = :_no_value, as: nil, label: nil, parse: nil, required: false, **input_html)
6
+ return datatable.filter if (name == nil && value == :_no_value) # This lets block methods call 'filter' and get the values
7
+
8
+ raise 'expected second argument to be a value' if value == :_no_value
9
+ raise 'parse must be a Proc' if parse.present? && !parse.kind_of?(Proc)
10
+
11
+ datatable._filters[name.to_sym] = {
12
+ value: value,
13
+ as: as,
14
+ label: label || name.to_s.titleize,
15
+ name: name.to_sym,
16
+ parse: parse,
17
+ required: required,
18
+ input_html: input_html
19
+ }
20
+ end
21
+
22
+ def scope(name = nil, *args, default: nil, label: nil)
23
+ return datatable.scope unless name # This lets block methods call 'scope' and get the values
24
+
25
+ datatable._scopes[name.to_sym] = {
26
+ default: default,
27
+ label: label || name.to_s.titleize,
28
+ name: name.to_sym,
29
+ args: args.presence
30
+ }
31
+ end
32
+
33
+ # This changes the filters from using an AJAX, to a POST or GET
34
+ def form(url: nil, verb: nil)
35
+ url ||= request.path
36
+ verb ||= (Rails.application.routes.recognize_path(url, method: :post).present? rescue false) ? :post : :get
37
+
38
+ datatable._form[:url] = url
39
+ datatable._form[:verb] = verb
40
+ end
41
+
42
+ def changes_columns_count
43
+ form()
44
+ end
45
+ alias_method :changes_column_count, :changes_columns_count
46
+
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,157 @@
1
+ module Effective
2
+ module EffectiveDatatable
3
+ module Format
4
+ BLANK = ''.freeze
5
+
6
+ private
7
+
8
+ def format(collection)
9
+ # We want to use the render :collection for each column that renders partials
10
+ rendered = {}
11
+
12
+ columns.each do |name, opts|
13
+ if opts[:partial] && state[:visible][name]
14
+ locals = {
15
+ datatable: self,
16
+ column: columns[name],
17
+ controller_namespace: controller_namespace
18
+ }.merge(actions_col_locals(opts)).merge(resource_col_locals(opts))
19
+
20
+ rendered[name] = (view.render(
21
+ partial: opts[:partial],
22
+ as: (opts[:partial_as] || :resource),
23
+ collection: collection.map { |row| row[opts[:index]] },
24
+ formats: :html,
25
+ locals: locals,
26
+ spacer_template: '/effective/datatables/spacer_template',
27
+ ) || '').split('EFFECTIVEDATATABLESSPACER')
28
+ end
29
+ end
30
+
31
+ collection.each_with_index do |row, row_index|
32
+ columns.each do |name, opts|
33
+ next unless state[:visible][name]
34
+
35
+ index = opts[:index]
36
+ value = row[index]
37
+
38
+ row[index] = (
39
+ if opts[:format] && opts[:as] == :actions
40
+ result = dsl_tool.instance_exec(value, row, &opts[:format])
41
+ "#{rendered[name][row_index]}#{result}"
42
+ elsif opts[:format]
43
+ dsl_tool.instance_exec(value, row, &opts[:format])
44
+ elsif opts[:partial]
45
+ rendered[name][row_index]
46
+ else
47
+ format_column(value, opts)
48
+ end
49
+ )
50
+ end
51
+ end
52
+ end
53
+
54
+ def format_column(value, column)
55
+ case column[:as]
56
+ when :boolean
57
+ case value
58
+ when true ; 'Yes'
59
+ when false ; 'No'
60
+ when String ; value
61
+ end
62
+ when :currency
63
+ view.number_to_currency(value) if value.present?
64
+ when :date
65
+ (value.strftime('%F') rescue BLANK) if value.present?
66
+ when :datetime
67
+ (value.strftime('%F %H:%M') rescue BLANK) if value.present?
68
+ when :decimal
69
+ value
70
+ when :duration
71
+ view.number_to_duration(value) if value.present?
72
+ when :effective_addresses
73
+ value.to_html if value.present?
74
+ when :effective_obfuscation
75
+ value
76
+ when :effective_roles
77
+ value.join(', ')
78
+ when :email
79
+ view.mail_to(value) if value.present?
80
+ when :integer
81
+ value
82
+ when :percentage
83
+ case value
84
+ when Integer ; "#{value}%"
85
+ when Numeric ; view.number_to_percentage(value * 100, precision: 2)
86
+ when String ; value
87
+ end
88
+ when :price
89
+ raise 'column type: price expects an Integer representing the number of cents' unless value.kind_of?(Integer)
90
+ view.number_to_currency(value / 100.0) if value.present?
91
+ else
92
+ value.to_s
93
+ end
94
+ end
95
+
96
+ def actions_col_locals(opts)
97
+ return {} unless opts[:as] == :actions
98
+ return { show_path: false, edit_path: false, destroy_path: false } unless active_record_collection?
99
+
100
+ locals = {}
101
+
102
+ locals[:show_action] = opts[:show]
103
+ locals[:edit_action] = opts[:edit]
104
+ locals[:destroy_action] = opts[:destroy]
105
+
106
+ if locals[:show_action] && (EffectiveDatatables.authorized?(view.controller, :show, collection_class) rescue false)
107
+ locals[:show_path] = resource.show_path(check: true)
108
+ else
109
+ locals[:show_path] = false
110
+ end
111
+
112
+ if locals[:edit_action] && (EffectiveDatatables.authorized?(view.controller, :edit, collection_class) rescue false)
113
+ locals[:edit_path] = resource.edit_path(check: true)
114
+ else
115
+ locals[:edit_path] = false
116
+ end
117
+
118
+ if locals[:destroy_action] && (EffectiveDatatables.authorized?(view.controller, :destroy, collection_class) rescue false)
119
+ locals[:destroy_path] = resource.destroy_path(check: true)
120
+ else
121
+ locals[:destroy_path] = false
122
+ end
123
+
124
+ locals
125
+ end
126
+
127
+ def resource_col_locals(opts)
128
+ return {} unless (resource = opts[:resource]).present?
129
+
130
+ locals = { name: opts[:name], macro: opts[:as], show_path: false, edit_path: false }
131
+
132
+ case opts[:action]
133
+ when :edit
134
+ if (EffectiveDatatables.authorized?(view.controller, :edit, resource.klass) rescue false)
135
+ locals[:edit_path] = resource.edit_path(check: true)
136
+ end
137
+ when :show
138
+ if (EffectiveDatatables.authorized?(view.controller, :show, resource.klass) rescue false)
139
+ locals[:show_path] = resource.show_path(check: true)
140
+ end
141
+ when false
142
+ # Nothing
143
+ else
144
+ # Fallback to defaults - check edit then show
145
+ if (EffectiveDatatables.authorized?(view.controller, :edit, resource.klass) rescue false)
146
+ locals[:edit_path] = resource.edit_path(check: true)
147
+ elsif (EffectiveDatatables.authorized?(view.controller, :show, resource.klass) rescue false)
148
+ locals[:show_path] = resource.show(check: true)
149
+ end
150
+ end
151
+
152
+ locals
153
+ end
154
+
155
+ end # / Rendering
156
+ end
157
+ end