Module: TransitionButtons::Transitionable

Extended by:
ActiveSupport::Concern
Defined in:
lib/transition_buttons/controller.rb

Overview

Mixed into a host controller to add a transition action:

class PostsController < ApplicationController
include TransitionButtons::Transitionable
end

Paired with the transitionable route helper:

resources :posts do
transitionable
end

This action is the real security boundary. The view's buttons are only a hint; here we independently re-resolve which events are legal-and-authorized for the current user before firing, and refuse anything else.

Instance Method Summary collapse

Instance Method Details

#transitionObject



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/transition_buttons/controller.rb', line 20

def transition
  record = transition_buttons_record
  machine = (params[:machine].presence || TransitionButtons.config.default_machine).to_sym
  event = params.require(:event).to_sym

  # Record who triggered the transition for the audit trail, if supported.
  record.current_actor = current_user if record.respond_to?(:current_actor=)

  resolver = EventResolver.new(record: record, user: current_user, machine: machine)

  if !resolver.domain_event?(event)
    transition_buttons_render_unavailable(record, event, machine)
  elsif !resolver.permitted?(event)
    transition_buttons_render_forbidden(record, event, machine)
  elsif resolver.fire(event)
    transition_buttons_render_success(record, event, machine)
  else
    # Legal and authorized, but the machine still refused (e.g. a guard that
    # flipped between resolution and firing). Surface it rather than hide it.
    transition_buttons_render_unavailable(record, event, machine)
  end
end