Class: Signoff::DSL
- Inherits:
-
Object
- Object
- Signoff::DSL
- Defined in:
- lib/signoff/dsl.rb
Overview
The receiver for the signoff do … end block. Every method here mutates the Signoff::Definition it was built with.
signoff do
state :draft
state :manager_review
state :approved
state :rejected
initial_state :draft
transition :draft, to: :manager_review
transition :manager_review, to: :approved
reject_to :rejected
allow_transition :manager_review do |user|
user.manager?
end
after_transition do |record, event|
WorkflowNotificationJob.perform_later(record.id, event.id)
end
end
Instance Method Summary collapse
-
#action(name, to:, from: nil) ⇒ Object
Declare a named custom action.
-
#after_transition(&block) ⇒ Object
Run
blockafter the transition’s transaction commits. -
#allow_transition(from_state, &block) ⇒ Object
Authorize transitions out of
from_state. -
#before_transition(&block) ⇒ Object
Run
blockinside the transition’s transaction, before the state column is written. -
#initial_state(name) ⇒ Object
Explicitly set the starting state.
-
#initialize(definition) ⇒ DSL
constructor
A new instance of DSL.
-
#reject_to(state) ⇒ Object
The state a record moves to when
reject!is called. -
#state(name, initial: false) ⇒ Object
Declare a state.
-
#states(*names) ⇒ Object
Declare several states at once: states :draft, :review, :approved.
-
#transition(from, to:) ⇒ Object
Declare a forward transition.
Constructor Details
#initialize(definition) ⇒ DSL
Returns a new instance of DSL.
29 30 31 |
# File 'lib/signoff/dsl.rb', line 29 def initialize(definition) @definition = definition end |
Instance Method Details
#action(name, to:, from: nil) ⇒ Object
Declare a named custom action. It generates a name! transition method and a can_name? predicate on the model, records an event whose action is the name verbatim, and is authorized by the same allow_transition guard as the source state. Like reject, the target is a side-transition (never a forward edge), so approve! stays unambiguous. This is the extension point for modelling any workflow verb beyond submit/approve/reject.
action :request_changes, from: :pending_review, to: :changes_requested
action :cancel, to: :cancelled # from any in-flight state
from is optional and may be a single state or an array; when omitted the action is allowed from every non-finalized state except its own target.
74 75 76 |
# File 'lib/signoff/dsl.rb', line 74 def action(name, to:, from: nil) @definition.add_action(name, to: to, from: from) end |
#after_transition(&block) ⇒ Object
Run block after the transition’s transaction commits. Receives (record, event). The created event is already persisted, so this is the right place to enqueue jobs or send mail.
102 103 104 105 106 |
# File 'lib/signoff/dsl.rb', line 102 def after_transition(&block) raise DefinitionError, "after_transition requires a block" unless block @definition.after_callbacks << block end |
#allow_transition(from_state, &block) ⇒ Object
Authorize transitions out of from_state. The block receives the acting user (and optionally the record) and must return a truthy value to allow the transition.
allow_transition :finance_review do |user, record|
user.finance_team? && record.amount <= user.approval_limit
end
85 86 87 88 89 |
# File 'lib/signoff/dsl.rb', line 85 def allow_transition(from_state, &block) raise DefinitionError, "allow_transition requires a block" unless block @definition.(from_state, block) end |
#before_transition(&block) ⇒ Object
Run block inside the transition’s transaction, before the state column is written. Receives (record, from_state, to_state).
93 94 95 96 97 |
# File 'lib/signoff/dsl.rb', line 93 def before_transition(&block) raise DefinitionError, "before_transition requires a block" unless block @definition.before_callbacks << block end |
#initial_state(name) ⇒ Object
Explicitly set the starting state. Defaults to the first declared state.
46 47 48 |
# File 'lib/signoff/dsl.rb', line 46 def initial_state(name) @definition.initial_state = name end |
#reject_to(state) ⇒ Object
The state a record moves to when reject! is called.
58 59 60 |
# File 'lib/signoff/dsl.rb', line 58 def reject_to(state) @definition.reject_state = state end |
#state(name, initial: false) ⇒ Object
Declare a state. Pass initial: true to mark it as the starting state (equivalent to a separate initial_state call).
35 36 37 38 |
# File 'lib/signoff/dsl.rb', line 35 def state(name, initial: false) @definition.add_state(name) @definition.initial_state = name if initial end |
#states(*names) ⇒ Object
Declare several states at once: states :draft, :review, :approved.
41 42 43 |
# File 'lib/signoff/dsl.rb', line 41 def states(*names) names.flatten.each { |name| state(name) } end |
#transition(from, to:) ⇒ Object
Declare a forward transition. Both from and to accept a single state or an array, so several source states can share one forward edge (e.g. transition [:draft, :rejected], to: :review).
53 54 55 |
# File 'lib/signoff/dsl.rb', line 53 def transition(from, to:) @definition.add_transition(from, to) end |