Module: HasState

Extended by:
ActiveSupport::Concern
Included in:
Reimbursement, Request
Defined in:
app/models/concerns/has_state.rb

Overview

Concern for state machines adding some convenient methods, notification capabilities and macro-style methods to define permissions

Defined Under Namespace

Modules: ClassMethods

Instance Method Summary collapse

Instance Method Details

#active?Boolean

Check whether is active (by default, 'active' means any state except canceled).

Returns:

  • (Boolean)

    if is active (not canceled)

See Also:



79
80
81
# File 'app/models/concerns/has_state.rb', line 79

def active?
  !canceled?
end

#assigned_rolesArray

Roles assigned to the machine according to its state

Returns:

  • (Array)

    list of roles as symbols

See Also:

  • roles_assigned_to


101
102
103
# File 'app/models/concerns/has_state.rb', line 101

def assigned_roles
  self.class.roles_assigned_to(state)
end

#can_be_destroyed?Boolean

Checks whether a user should be allowed to completely delete the object.

Returns:

  • (Boolean)

    true if allowed



129
130
131
# File 'app/models/concerns/has_state.rb', line 129

def can_be_destroyed?
  !with_transitions?
end

#can_cancel?Boolean

Checks whether can have a transition to 'canceled' state

Compatibility for #cancel with transitions defined by state_machine. Default implementation always return true when active, meaning that a process can be canceled at any moment. Classes using this mixin should implement their own custom behaviour. return [Boolean] true if #cancel can be called

Returns:

  • (Boolean)

See Also:



93
94
95
# File 'app/models/concerns/has_state.rb', line 93

def can_cancel?
  active?
end

#cancelObject

Sets the state to 'canceled'

It works exactly in the same way that any other transition defined by state_machine. It's implemented in a separate way to keep the workflow as clean as possible. Since a cancelation can happen at any moment, implementing it as a regular transition could lead state_machine to the conclusion that 'canceled' is the only valid final state.

return [Boolean] true if the state is updated



67
68
69
70
71
72
# File 'app/models/concerns/has_state.rb', line 67

def cancel
  return false unless can_cancel?

  self.state = 'canceled'
  save
end

#editable?Boolean

Checks whether the requester should be allowed to do changes.

Returns:

  • (Boolean)

    true if allowed



122
123
124
# File 'app/models/concerns/has_state.rb', line 122

def editable?
  in_initial_state?
end

#human_state_descriptionObject

Localized state description, to complete human_state_name

return [String] localized description of the current state



108
109
110
# File 'app/models/concerns/has_state.rb', line 108

def human_state_description
  I18n.t(state, scope: "activerecord.models.#{self.class.model_name.singular}.states")
end

#human_state_guideObject

Localized guide of the next step, based in current state

return [String] localized guide text



115
116
117
# File 'app/models/concerns/has_state.rb', line 115

def human_state_guide
  I18n.t(state, scope: "activerecord.models.#{self.class.model_name.singular}.state_guides")
end

#in_final_state?Boolean

Checks if the object have reached a final state

Returns:

  • (Boolean)

    true if no possible transitions left



38
39
40
# File 'app/models/concerns/has_state.rb', line 38

def in_final_state?
  state_events(guard: false).empty?
end

#in_initial_state?Boolean

Checks if the object is in the initial state

Returns:

  • (Boolean)

    true if the current state is the initial one



45
46
47
# File 'app/models/concerns/has_state.rb', line 45

def in_initial_state?
  self.class.state_machines[:state].initial_state(self).name == state_name
end

#labelString

Label to identify the state machine

Returns:

  • (String)

    label based in the id



136
137
138
# File 'app/models/concerns/has_state.rb', line 136

def label
  "##{id}"
end

#notify_stateObject

Notify the current state to the users designed using HasState.notify_state

See Also:

  • notify_to


52
53
54
55
56
# File 'app/models/concerns/has_state.rb', line 52

def notify_state
  people = self.class.roles_notified_when(state)
  people.map! { |i| i.to_sym == :requester ? user : i }
  HasStateMailer.notify_to(people, :state, self)
end

#titleString

Title to show the state machine in the UI

Returns:

  • (String)

    Class name and label



143
144
145
# File 'app/models/concerns/has_state.rb', line 143

def title
  "#{self.class.model_name.human} #{label}"
end

#with_transitions?Boolean

Checks whether the object has changed its state at least once in the past, no matters which the current state is.

Returns:

  • (Boolean)

    true if it has have some transition



31
32
33
# File 'app/models/concerns/has_state.rb', line 31

def with_transitions?
  !transitions.empty?
end