effective_resources 0.9.5 → 0.10.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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/concerns/effective/crud_controller.rb +23 -546
  3. data/app/controllers/concerns/effective/crud_controller/actions.rb +289 -0
  4. data/app/controllers/concerns/effective/crud_controller/dsl.rb +81 -0
  5. data/app/controllers/concerns/effective/crud_controller/paths.rb +87 -0
  6. data/app/controllers/concerns/effective/crud_controller/permitted_params.rb +66 -0
  7. data/app/controllers/concerns/effective/crud_controller/save.rb +77 -0
  8. data/app/controllers/concerns/effective/crud_controller/submits.rb +122 -0
  9. data/app/helpers/effective_resources_helper.rb +51 -52
  10. data/app/helpers/effective_resources_private_helper.rb +69 -0
  11. data/app/models/concerns/effective_resource.rb +24 -0
  12. data/app/models/effective/model_reader.rb +29 -0
  13. data/app/models/effective/resource.rb +6 -2
  14. data/app/models/effective/resources/actions.rb +10 -10
  15. data/app/models/effective/resources/associations.rb +5 -0
  16. data/app/models/effective/resources/attributes.rb +40 -27
  17. data/app/models/effective/resources/controller.rb +81 -0
  18. data/app/models/effective/resources/forms.rb +0 -51
  19. data/app/models/effective/resources/init.rb +19 -17
  20. data/app/models/effective/resources/klass.rb +6 -8
  21. data/app/models/effective/resources/model.rb +23 -0
  22. data/app/models/effective/resources/naming.rb +7 -3
  23. data/app/models/effective/resources/paths.rb +4 -63
  24. data/app/models/effective/resources/relation.rb +4 -1
  25. data/app/models/effective/resources/sql.rb +1 -1
  26. data/app/views/application/create.js.erb +1 -1
  27. data/app/views/application/edit.html.haml +2 -2
  28. data/app/views/application/index.html.haml +1 -1
  29. data/app/views/application/member_action.js.erb +1 -1
  30. data/app/views/application/new.html.haml +3 -1
  31. data/app/views/application/show.html.haml +1 -1
  32. data/app/views/application/update.js.erb +1 -1
  33. data/app/views/effective/resource/_actions.html.haml +3 -32
  34. data/app/views/effective/resource/_actions_dropleft.html.haml +4 -26
  35. data/app/views/effective/resource/_actions_glyphicons.html.haml +4 -10
  36. data/lib/effective_resources/engine.rb +1 -0
  37. data/lib/effective_resources/version.rb +1 -1
  38. metadata +14 -3
@@ -0,0 +1,66 @@
1
+ module Effective
2
+ module CrudController
3
+ module PermittedParams
4
+ BLACKLIST = [:created_at, :updated_at]
5
+
6
+ # This is only available to models that use the effective_resource do ... end attributes block
7
+ # It will be called last, and only for those resources
8
+ # params.require(effective_resource.name).permit!
9
+ def resource_permitted_params
10
+ raise 'expected resource class to have effective_resource do .. end' if effective_resource.model.blank?
11
+
12
+ permitted_params = permitted_params_for(resource)
13
+
14
+ if Rails.env.development?
15
+ Rails.logger.info "Effective::CrudController#resource_permitted_params:"
16
+ Rails.logger.info "params.require(:#{effective_resource.name}).permit(#{permitted_params.to_s[1...-1]})"
17
+ end
18
+
19
+ params.require(effective_resource.name).permit(*permitted_params)
20
+ end
21
+
22
+ private
23
+
24
+ def permitted_params_for(resource)
25
+ effective_resource = if resource.kind_of?(Class)
26
+ resource.effective_resource if resource.respond_to?(:effective_resource)
27
+ else
28
+ resource.class.effective_resource if resource.class.respond_to?(:effective_resource)
29
+ end
30
+
31
+ # That class doesn't implement effective_resource do .. end block
32
+ return [] unless effective_resource.present?
33
+
34
+ # This is :id, all belongs_to ids, and model attributes
35
+ permitted_params = effective_resource.permitted_attributes.select do |name, (_, atts)|
36
+ if BLACKLIST.include?(name)
37
+ false
38
+ elsif atts.blank? || !atts.key?(:permitted)
39
+ true # Default is true
40
+ else
41
+ permitted = (atts[:permitted].respond_to?(:call) ? instance_exec(&atts[:permitted]) : atts[:permitted])
42
+
43
+ if permitted == true || permitted == false
44
+ permitted
45
+ elsif permitted == nil || permitted == :blank
46
+ effective_resource.namespaces.length == 0
47
+ else # A symbol, string, or array of, representing the namespace
48
+ (effective_resource.namespaces & Array(permitted).map(&:to_s)).present?
49
+ end
50
+ end
51
+ end.keys
52
+
53
+ # Recursively add any accepts_nested_resources
54
+ effective_resource.nested_resources.each do |nested|
55
+ if (nested_params = permitted_params_for(nested.klass)).present?
56
+ nested_params.insert(nested_params.rindex { |obj| !obj.kind_of?(Hash)} + 1, :_destroy)
57
+ permitted_params << { "#{nested.plural_name}_attributes".to_sym => nested_params }
58
+ end
59
+ end
60
+
61
+ permitted_params
62
+ end
63
+
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,77 @@
1
+ module Effective
2
+ module CrudController
3
+ module Save
4
+
5
+ # Based on the incoming params[:commit] or passed action. Merges all options.
6
+ def commit_action(action = nil)
7
+ config = (['create', 'update'].include?(params[:action]) ? self.class.submits : self.class.buttons)
8
+
9
+ commit = if action.present?
10
+ config[action.to_s] || config.find { |_, v| v[:action] == action }.try(:last) || { action: action }
11
+ else
12
+ config[params[:commit].to_s] || config.find { |_, v| v[:action] == :save }.try(:last) || { action: :save }
13
+ end
14
+
15
+ commit.reverse_merge!(self.class.ons[commit[:action]]) if self.class.ons[commit[:action]]
16
+
17
+ commit
18
+ end
19
+
20
+ # This calls the appropriate member action, probably save!, on the resource.
21
+ def save_resource(resource, action = :save, &block)
22
+ raise "expected @#{resource_name} to respond to #{action}!" unless resource.respond_to?("#{action}!")
23
+
24
+ resource.current_user ||= current_user if resource.respond_to?(:current_user=)
25
+
26
+ ActiveRecord::Base.transaction do
27
+ begin
28
+ if resource.public_send("#{action}!") == false
29
+ raise("failed to #{action} #{resource}")
30
+ end
31
+
32
+ yield if block_given?
33
+
34
+ run_callbacks(:resource_save)
35
+ return true
36
+ rescue => e
37
+ Rails.logger.info "Failed to #{action}: #{e.message}" if Rails.env.development?
38
+
39
+ if resource.respond_to?(:restore_attributes) && resource.persisted?
40
+ resource.restore_attributes(['status', 'state'])
41
+ end
42
+
43
+ flash.delete(:success)
44
+ flash.now[:danger] = flash_danger(resource, action, e: e)
45
+ raise ActiveRecord::Rollback
46
+ end
47
+ end
48
+
49
+ run_callbacks(:resource_error)
50
+ false
51
+ end
52
+
53
+ def resource_flash(status, resource, action)
54
+ submit = commit_action(action)
55
+ message = submit[status].respond_to?(:call) ? instance_exec(&submit[status]) : submit[status]
56
+ return message if message.present?
57
+
58
+ case status
59
+ when :success then flash_success(resource, action)
60
+ when :danger then flash_danger(resource, action)
61
+ else
62
+ raise "unknown resource flash status: #{status}"
63
+ end
64
+ end
65
+
66
+ def reload_resource
67
+ self.resource.reload if resource.respond_to?(:reload)
68
+ end
69
+
70
+ # Should return a new resource based on the passed one
71
+ def duplicate_resource(resource)
72
+ resource.dup
73
+ end
74
+
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,122 @@
1
+ module Effective
2
+ module CrudController
3
+ module Submits
4
+ extend ActiveSupport::Concern
5
+
6
+ module ClassMethods
7
+ # { 'Save' => { action: save, ...}}
8
+ def submits
9
+ @_effective_submits ||= effective_resource.submits
10
+ end
11
+
12
+ # { 'Approve' => { action: approve, ...}}
13
+ def buttons
14
+ @_effective_buttons ||= effective_resource.buttons
15
+ end
16
+
17
+ # { :approve => { redirect: .. }}
18
+ def ons
19
+ @_effective_ons ||= effective_resource.ons
20
+ end
21
+
22
+ # :only, :except, :if, :unless, :redirect, :success, :danger, :class
23
+ def _insert_submit(action, label = nil, args = {})
24
+ raise 'expected args to be a Hash or false' unless args.kind_of?(Hash) || args == false
25
+
26
+ if label == false
27
+ submits.delete_if { |label, args| args[:action] == action }; return
28
+ end
29
+
30
+ if args == false
31
+ submits.delete(label); return
32
+ end
33
+
34
+ if label # Overwrite the default member action when given a custom submit
35
+ submits.delete_if { |label, args| args[:default] && args[:action] == action }
36
+ end
37
+
38
+ if args.key?(:if) && args[:if].respond_to?(:call) == false
39
+ raise "expected if: to be callable. Try submit :approve, 'Save and Approve', if: -> { finished? }"
40
+ end
41
+
42
+ if args.key?(:unless) && args[:unless].respond_to?(:call) == false
43
+ raise "expected unless: to be callable. Try submit :approve, 'Save and Approve', unless: -> { declined? }"
44
+ end
45
+
46
+ if args.key?(:only)
47
+ args[:only] = Array(args[:only])
48
+ raise "expected only: to be a symbol or array of symbols. Try submit :approve, 'Save and Approve', only: [:edit]" unless args[:only].all? { |v| v.kind_of?(Symbol) }
49
+ end
50
+
51
+ if args.key?(:except)
52
+ args[:except] = Array(args[:except])
53
+ raise "expected except: to be a symbol or array of symbols. Try submit :approve, 'Save and Approve', except: [:edit]" unless args[:except].all? { |v| v.kind_of?(Symbol) }
54
+ end
55
+
56
+ if args.key?(:redirect_to) # Normalize this option to redirect
57
+ args[:redirect] = args.delete(:redirect_to)
58
+ end
59
+
60
+ args[:action] = action
61
+
62
+ (submits[label] ||= {}).merge!(args)
63
+ end
64
+
65
+ def _insert_button(action, label = nil, args = {})
66
+ raise 'expected args to be a Hash or false' unless args.kind_of?(Hash) || args == false
67
+
68
+ if label == false
69
+ buttons.delete_if { |label, args| args[:action] == action }; return
70
+ end
71
+
72
+ if args == false
73
+ buttons.delete(label); return
74
+ end
75
+
76
+ if label # Overwrite the default member action when given a custom label
77
+ buttons.delete_if { |label, args| args[:default] && args[:action] == action }
78
+ end
79
+
80
+ if args.key?(:if) && args[:if].respond_to?(:call) == false
81
+ raise "expected if: to be callable. Try button :approve, 'Approve', if: -> { finished? }"
82
+ end
83
+
84
+ if args.key?(:unless) && args[:unless].respond_to?(:call) == false
85
+ raise "expected unless: to be callable. Try button :approve, 'Approve', unless: -> { declined? }"
86
+ end
87
+
88
+ if args.key?(:only)
89
+ args[:only] = Array(args[:only])
90
+ raise "expected only: to be a symbol or array of symbols. Try button :approve, 'Save and Approve', only: [:edit]" unless args[:only].all? { |v| v.kind_of?(Symbol) }
91
+ end
92
+
93
+ if args.key?(:except)
94
+ args[:except] = Array(args[:except])
95
+ raise "expected except: to be a symbol or array of symbols. Try button :approve, 'Save and Approve', except: [:edit]" unless args[:except].all? { |v| v.kind_of?(Symbol) }
96
+ end
97
+
98
+ if args.key?(:redirect_to) # Normalize this option to redirect
99
+ args[:redirect] = args.delete(:redirect_to)
100
+ end
101
+
102
+ args[:action] = action
103
+
104
+ (buttons[label] ||= {}).merge!(args)
105
+ end
106
+
107
+ def _insert_on(action, args = {})
108
+ raise 'expected args to be a Hash' unless args.kind_of?(Hash)
109
+
110
+ if args.key?(:redirect_to) # Normalize this option to redirect
111
+ args[:redirect] = args.delete(:redirect_to)
112
+ end
113
+
114
+ args[:action] = action
115
+
116
+ (ons[action] ||= {}).merge!(args)
117
+ end
118
+ end
119
+
120
+ end
121
+ end
122
+ end
@@ -1,41 +1,49 @@
1
1
  module EffectiveResourcesHelper
2
2
 
3
- def effective_submit(form, options = {}, &block) # effective_bootstrap
4
- resource = (controller.class.respond_to?(:effective_resource) ? controller.class.effective_resource : Effective::Resource.new(controller_path))
5
- actions = resource.submits_for(form.object, controller: controller)
6
- buttons = actions.map { |name, opts| form.save(name, opts) }.join.html_safe
3
+ # effective_bootstrap
4
+ def effective_submit(form, options = {}, &block)
5
+ actions = (controller.respond_to?(:effective_resource) ? controller.class : find_effective_resource).submits
6
+ actions = permitted_resource_actions(form.object, actions)
7
+
8
+ submits = actions.map { |name, opts| form.save(name, opts.except(:action, :title, 'data-method', 'data-confirm')) }.join.html_safe
7
9
 
8
10
  form.submit('', options) do
9
- (block_given? ? capture(&block) : ''.html_safe) + buttons
11
+ (block_given? ? capture(&block) : ''.html_safe) + submits
10
12
  end
11
13
  end
12
14
 
13
15
  # effective_form_inputs
14
16
  def simple_form_submit(form, options = {}, &block)
15
- resource = (controller.class.respond_to?(:effective_resource) ? controller.class.effective_resource : Effective::Resource.new(controller_path))
16
- actions = resource.submits_for(form.object, controller: controller)
17
+ actions = (controller.respond_to?(:effective_resource) ? controller.class : find_effective_resource).submits
18
+ actions = permitted_resource_actions(form.object, actions)
17
19
 
18
- buttons = actions.map { |action| form.button(:submit, *action) }
20
+ submits = actions.map { |name, opts| form.button(:submit, name, opts.except(:action, :title, 'data-method', 'data-confirm')) }.join('&nbsp;').html_safe
19
21
 
20
22
  # I think this is a bug. I can't override default button class when passing my own class: variable. it merges them.
21
- if defined?(SimpleForm) && (btn_class = SimpleForm.button_class).present?
22
- buttons = buttons.map { |button| button.sub(btn_class, '') }
23
+ if (btn_class = SimpleForm.button_class).present?
24
+ submits = submits.map { |submit| submit.sub(btn_class, '') }
23
25
  end
24
26
 
25
27
  wrapper_options = { class: 'form-actions' }.merge(options.delete(:wrapper_html) || {})
26
28
 
27
29
  content_tag(:div, wrapper_options) do
28
- (block_given? ? capture(&block) : ''.html_safe) + buttons.join('&nbsp;').html_safe
30
+ (block_given? ? capture(&block) : ''.html_safe) + submits
29
31
  end
30
32
  end
31
33
 
32
- def simple_form_save(form, label = 'Save', options = {}, &block)
33
- wrapper_options = { class: 'form-actions' }.merge(options.delete(:wrapper_html) || {})
34
- options = { class: 'btn btn-primary', data: { disable_with: 'Saving...'} }.merge(options)
34
+ def render_resource_buttons(resource, atts = {}, &block)
35
+ effective_resource = find_effective_resource
36
+ actions = (controller.respond_to?(:effective_resource) ? controller.class : effective_resource).buttons
35
37
 
36
- content_tag(:div, wrapper_options) do
37
- form.button(:submit, label, options) + (capture(&block) if block_given?)
38
+ actions = if resource.kind_of?(Class)
39
+ actions.select { |_, v| effective_resource.collection_get_actions.include?(v[:action]) }
40
+ elsif resource.respond_to?(:persisted?) && resource.persisted?
41
+ actions.select { |_, v| effective_resource.member_actions.include?(v[:action]) }
42
+ else
43
+ {}
38
44
  end
45
+
46
+ render_resource_actions(resource, atts.merge(actions: actions), &block)
39
47
  end
40
48
 
41
49
  # Renders the effective/resource view partial for this resource
@@ -46,29 +54,34 @@ module EffectiveResourcesHelper
46
54
  # partial: :dropleft|:glyphicons|string
47
55
  # locals: {} render locals
48
56
  # you can also pass all action names and true/false such as edit: true, show: false
49
- def render_resource_actions(resource, instance = nil, atts = {}, &block)
50
- (atts = instance; instance = nil) if instance.kind_of?(Hash) && atts.blank?
51
- raise 'expected first argument to be an Effective::Resource' unless resource.kind_of?(Effective::Resource)
57
+ def render_resource_actions(resource, atts = {}, &block)
58
+ raise 'expected first argument to be an ActiveRecord::Base object or Array of objects' unless resource.kind_of?(ActiveRecord::Base) || resource.kind_of?(Class) || resource.kind_of?(Array)
52
59
  raise 'expected attributes to be a Hash' unless atts.kind_of?(Hash)
53
60
 
54
61
  locals = atts.delete(:locals) || {}
55
- namespace = atts.delete(:namespace) || (resource.namespace.to_sym if resource.namespace)
56
62
  partial = atts.delete(:partial)
57
63
  spacer_template = locals.delete(:spacer_template)
58
64
 
59
- partial = ['effective/resource/actions', partial.to_s].join('_') if partial.kind_of?(Symbol)
60
- partial = (partial.presence || 'effective/resource/actions') + '.html'
65
+ effective_resource = (atts.delete(:effective_resource) || find_effective_resource)
66
+ actions = atts.delete(:actions) || effective_resource.resource_actions
67
+ namespace = atts.delete(:namespace) || (effective_resource.namespace.to_sym if effective_resource.namespace)
61
68
 
62
- actions = (instance ? (resource.member_get_actions + resource.member_delete_actions) : resource.collection_get_actions)
63
- actions = (actions & resource.crud_actions) if atts.delete(:crud)
69
+ # Filter Actions
70
+ action_keys = actions.map { |_, v| v[:action] }
71
+ raise "unknown action for #{effective_resource.name}: #{(atts.keys - action_keys).join(' ')}." if (atts.keys - action_keys).present?
72
+ actions = actions.select { |_, v| atts[v[:action]].respond_to?(:call) ? instance_exec(&atts[v[:action]]) : (atts[v[:action]] != false) }
64
73
 
65
- raise "unknown action for #{resource.name}: #{(atts.keys - actions).join(' ')}." if (atts.keys - actions).present?
66
- actions = (actions - atts.reject { |_, v| v }.keys + atts.select { |_, v| v }.keys).uniq
74
+ # Select Partial
75
+ partial = ['effective/resource/actions', partial.to_s].join('_') if partial.kind_of?(Symbol)
76
+ partial = (partial.presence || 'effective/resource/actions') + '.html'
67
77
 
68
- locals = { resource: instance, effective_resource: resource, namespace: namespace, actions: actions }.compact.merge(locals)
78
+ # Assign Locals
79
+ locals = { resource: resource, effective_resource: effective_resource, namespace: namespace, actions: actions }.compact.merge(locals)
69
80
 
70
- if instance.kind_of?(Array)
71
- render(partial: partial, collection: instance, as: :resource, locals: locals.except(:resource), spacer_template: spacer_template)
81
+ # Render
82
+ if resource.kind_of?(Array)
83
+ locals[:format_block] = block if block_given?
84
+ render(partial: partial, collection: resource, as: :resource, locals: locals.except(:resource), spacer_template: spacer_template)
72
85
  elsif block_given?
73
86
  render(partial, locals) { yield }
74
87
  else
@@ -77,43 +90,29 @@ module EffectiveResourcesHelper
77
90
  end
78
91
 
79
92
  # When called from /admin/things/new.html.haml this will render 'admin/things/form', or 'things/form', or 'thing/form'
80
- def render_resource_form(resource, instance = nil, atts = {})
81
- (atts = instance; instance = nil) if instance.kind_of?(Hash) && atts.blank?
82
- raise 'expected first argument to be an Effective::Resource' unless resource.kind_of?(Effective::Resource)
93
+ def render_resource_form(resource, atts = {})
94
+ raise 'expected first argument to be an ActiveRecord::Base object' unless resource.kind_of?(ActiveRecord::Base)
83
95
  raise 'expected attributes to be a Hash' unless atts.kind_of?(Hash)
84
96
 
85
- instance = instance || instance_variable_get('@' + resource.name) || resource.instance
86
- raise "unable to find resource instance. Either pass the instance as the second argument, or assign @#{resource.name}" unless instance
97
+ effective_resource = (atts.delete(:effective_resource) || find_effective_resource)
87
98
 
88
99
  action = atts.delete(:action)
89
- atts = { :namespace => (resource.namespace.to_sym if resource.namespace), resource.name.to_sym => instance }.compact.merge(atts)
100
+ atts = { :namespace => (effective_resource.namespace.to_sym if effective_resource.namespace), effective_resource.name.to_sym => resource }.compact.merge(atts)
90
101
 
91
102
  if lookup_context.template_exists?("form_#{action}", controller._prefixes, :partial)
92
103
  render "form_#{action}", atts
93
104
  elsif lookup_context.template_exists?('form', controller._prefixes, :partial)
94
105
  render 'form', atts
95
- elsif lookup_context.template_exists?('form', resource.plural_name, :partial)
96
- render "#{resource.plural_name}/form", atts
97
- elsif lookup_context.template_exists?('form', resource.name, :partial)
98
- render "#{resource.name}/form", atts
106
+ elsif lookup_context.template_exists?('form', effective_resource.plural_name, :partial)
107
+ render "#{effective_resource.plural_name}/form", atts
108
+ elsif lookup_context.template_exists?('form', effective_resource.name, :partial)
109
+ render "#{effective_resource.name}/form", atts
99
110
  else
100
111
  render 'form', atts # Will raise the regular error
101
112
  end
102
113
  end
103
114
 
104
- def number_to_duration(duration)
105
- duration = duration.to_i
106
- value = duration.abs
107
-
108
- [
109
- ('-' if duration < 0),
110
- ("#{value / 60}h " if value >= 60),
111
- ("#{'%0.2d' % (value % 60)}m" if value > 0),
112
- ('0m' if value == 0),
113
- ].compact.join
114
- end
115
-
116
- ### Tableize attributes
115
+ # Tableize attributes
117
116
  # This is used by effective_orders, effective_logging, effective_trash and effective_mergery
118
117
  def tableize_hash(obj, table: 'table', th: true, sub_table: 'table', sub_th: true, flatten: true)
119
118
  case obj
@@ -0,0 +1,69 @@
1
+ module EffectiveResourcesPrivateHelper
2
+ REPLACE_PAGE_ACTIONS = {'update' => :edit, 'create' => :new}
3
+
4
+ def permitted_resource_actions(resource, actions, effective_resource = nil)
5
+ effective_resource ||= find_effective_resource
6
+
7
+ page_action = REPLACE_PAGE_ACTIONS[params[:action]] || params[:action]&.to_sym || :save
8
+
9
+ actions.select do |commit, args|
10
+ action = (args[:action] == :save ? (resource.new_record? ? :create : :update) : args[:action])
11
+
12
+ (args.key?(:only) ? args[:only].include?(page_action) : true) &&
13
+ (args.key?(:except) ? !args[:except].include?(page_action) : true) &&
14
+ (args.key?(:if) ? controller.instance_exec(&args[:if]) : true) &&
15
+ (args.key?(:unless) ? !controller.instance_exec(&args[:unless]) : true) &&
16
+ EffectiveResources.authorized?(controller, action, resource)
17
+ end.transform_values.with_index do |opts, index|
18
+ action = opts[:action]
19
+
20
+ # Transform data: { ... } hash into 'data-' keys
21
+ data.each { |k, v| opts["data-#{k}"] ||= v } if (data = opts.delete(:data))
22
+
23
+ # Assign data method and confirm
24
+ if effective_resource.member_post_actions.include?(action)
25
+ opts['data-method'] ||= :post
26
+ opts['data-confirm'] ||= "Really #{action} @resource?"
27
+ elsif effective_resource.member_delete_actions.include?(action)
28
+ opts['data-method'] ||= :delete
29
+ opts['data-confirm'] ||= "Really #{action == :destroy ? 'delete' : action.to_s.titleize} @resource?"
30
+ end
31
+
32
+ # Assign class
33
+ opts[:class] ||= (
34
+ if opts['data-method'] == :delete
35
+ 'btn btn-danger'
36
+ elsif index == 0
37
+ 'btn btn-primary'
38
+ elsif defined?(EffectiveBootstrap)
39
+ 'btn btn-secondary'
40
+ else
41
+ 'btn btn-default'
42
+ end
43
+ )
44
+
45
+ # Assign title
46
+ unless action == :save
47
+ opts[:title] ||= case action
48
+ when :edit then "Edit #{resource}"
49
+ when :show then "#{resource}"
50
+ when :destroy then "Delete #{resource}"
51
+ when :index then "All #{effective_resource.human_plural_name.titleize}"
52
+ else "#{action.to_s.titleize} #{resource}"
53
+ end
54
+ end
55
+
56
+ # Replace resource name in any token strings
57
+ if opts['data-confirm']
58
+ opts['data-confirm'].gsub!('@resource', (resource.to_s.presence || effective_resource.human_name))
59
+ end
60
+
61
+ opts.except(:default, :only, :except, :if, :unless, :redirect, :success, :danger)
62
+ end
63
+ end
64
+
65
+ def find_effective_resource
66
+ @_effective_resource ||= (controller.respond_to?(:effective_resource) ? controller.effective_resource : Effective::Resource.new(controller_path))
67
+ end
68
+
69
+ end