Module: HasState::ClassMethods
- Defined in:
- app/models/concerns/has_state.rb
Overview
Class methods
Instance Method Summary collapse
-
#allow_transition(transition_name, roles) ⇒ Object
Macro-style method to define which roles are allowed to trigger a transition.
-
#assign_state(state_name, opts = {}) ⇒ Object
Macro-style method to define the role which is responsible of the next action for a given state.
-
#notify_inactive ⇒ Object
Sends notifications for all the objects that are stuck in a given state, according to the timeouts and roles specified using notify_to.
-
#notify_state(state_name, opts = {}) ⇒ Object
Macro-style method to define who should be notified in every state.
-
#roles_assigned_to(state) ⇒ Array
Queries the state - role assignation performed via assign_state.
-
#roles_notified_when(state) ⇒ Array
Queries the state - role assignation performed via notify_state.
-
#states_assigned_to(role) ⇒ Array
Queries the state - role assignation performed via assign_state.
-
#transitions ⇒ Array<Symbol>
Defined transitions (including :cancel).
Instance Method Details
#allow_transition(transition_name, roles) ⇒ Object
Macro-style method to define which roles are allowed to trigger a transition.
It works by defining a method called allow_xxx? (where xxx is the name of the transition). If more complex check is needed, the method can be explicity defined (not using allow_transition).
242 243 244 245 246 247 |
# File 'app/models/concerns/has_state.rb', line 242 def allow_transition(transition_name, roles) roles = [roles].flatten.map(&:to_sym) define_method :"allow_#{transition_name}?" do |role_name| roles.include? role_name.to_sym end end |
#assign_state(state_name, opts = {}) ⇒ Object
Macro-style method to define the role which is responsible of the next action for a given state. Currently, this definition is only used to set default filters on lists.
168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
# File 'app/models/concerns/has_state.rb', line 168 def assign_state(state_name, opts = {}) to = opts[:to] if to.blank? false else @assigned_states ||= {} @assigned_states[to.to_sym] ||= [] @assigned_states[to.to_sym] << state_name.to_sym @assigned_roles ||= {} @assigned_roles[state_name.to_sym] ||= [] @assigned_roles[state_name.to_sym] << to.to_sym true end end |
#notify_inactive ⇒ Object
Sends notifications for all the objects that are stuck in a given state, according to the timeouts and roles specified using notify_to
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 |
# File 'app/models/concerns/has_state.rb', line 293 def notify_inactive # Leaf classes send notifications if subclasses.blank? return true unless @reminder_timeouts machines = joins(:user) @reminder_timeouts.each do |state, time| next unless time machines.where(state: state).where(["COALESCE(state_updated_at, #{table_name}.created_at) < ?", time.ago]).each do |m| people = @reminder_roles[state].map { |i| i.to_sym == :requester ? m.user : i } HasStateMailer.notify_to(people, :state, m) end end # But 'abstract' subclasses delegate to subclasses else subclasses.each(&:notify_inactive) true end end |
#notify_state(state_name, opts = {}) ⇒ Object
Macro-style method to define who should be notified in every state.
Understands 3 different options, all of them optional
:to Role or array of roles. Who should be notified when the machine enters the state. The special value :requester represent the requester user, despite the user's role.
:remind_after Threshold in seconds. If the machine has been in the same state for a period of time longer than the threshold, a reminder notification is sent.
:remind_to Role or array of roles. Reminders will use this, if present, instead of :to.
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
# File 'app/models/concerns/has_state.rb', line 208 def notify_state(state_name, opts = {}) @notified_roles ||= {} @reminder_timeouts ||= {} @reminder_roles ||= {} st = state_name.to_sym to = opts[:to] @notified_roles[st] = if to.blank? [] else [to].flatten.map(&:to_sym) end remind = opts.key?(:remind_to) ? opts[:remind_to] : to if remind.blank? @reminder_roles[st] = [] @reminder_timeouts[st] = nil else @reminder_roles[st] = [remind].flatten.map(&:to_sym) @reminder_timeouts[st] = opts[:remind_after] end true end |
#roles_assigned_to(state) ⇒ Array
Queries the state - role assignation performed via assign_state
275 276 277 |
# File 'app/models/concerns/has_state.rb', line 275 def roles_assigned_to(state) @assigned_roles[state.to_sym] ? @assigned_roles[state.to_sym].dup : [] end |
#roles_notified_when(state) ⇒ Array
Queries the state - role assignation performed via notify_state
285 286 287 |
# File 'app/models/concerns/has_state.rb', line 285 def roles_notified_when(state) @notified_roles[state.to_sym] ? @notified_roles[state.to_sym].dup : [] end |
#states_assigned_to(role) ⇒ Array
Queries the state - role assignation performed via assign_state
261 262 263 264 265 266 267 268 |
# File 'app/models/concerns/has_state.rb', line 261 def states_assigned_to(role) name = if role.is_a?(UserRole) role.name else role.to_sym end @assigned_states[name] ? @assigned_states[name].dup : [] end |
#transitions ⇒ Array<Symbol>
Defined transitions (including :cancel)
252 253 254 |
# File 'app/models/concerns/has_state.rb', line 252 def transitions state_machines[:state].events.map(&:name) + [:cancel] end |