class Hobo::Model::Lifecycles::Lifecycle

Attributes

creators[RW]
default_state[RW]
invariants[RW]
model[RW]
options[RW]
states[RW]
transitions[RW]
active_step[RW]
provided_key[RW]
record[R]

— Instance Features — #

Public Instance Methods

active_step_is?(name) click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 227
def active_step_is?(name)
  active_step && active_step.name == name.to_sym
end
available_transitions() click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 137
def available_transitions
  state ? state.transitions_out : []
end
available_transitions_for(user, name=nil) click to toggle source

see also #publishable_transitions_for

# File lib/hobo/model/lifecycles/lifecycle.rb, line 142
def available_transitions_for(user, name=nil)
  name = name.to_sym if name
  matches = available_transitions
  matches = matches.select { |t| t.name == name } if name
  record.with_acting_user(user) do
    matches.select { |t| t.can_run?(record) }
  end
end
become(state_name, validate=true) click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 160
def become(state_name, validate=true)
  state_name = state_name.to_sym
  record.send :write_attribute, self.class.state_field, state_name.to_s

  if state_name == :destroy
    record.destroy
    true
  else
    s = self.class.states[state_name]
    raise ArgumentError, "No such state '#{state_name}' for #{record.class.name}" unless s

    if record.save(:validate => validate)
      s.activate! record
      self.active_step = nil # That's the end of this step
      true
    else
      false
    end
  end
end
can_transition?(name, user) click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 110
def can_transition?(name, user)
  available_transitions_for(user, name).any?
end
clear_key() click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 218
def clear_key
  record.send :write_attribute, key_timestamp_field, nil
end
find_transition(name, user) click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 121
def find_transition(name, user)
  available_transitions_for(user, name).first
end
generate_key() click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 190
def generate_key
  if Time.zone.nil?
    raise RuntimeError, "Cannot generate lifecycle key timestamp if the time-zone is not configured. Please add, e.g. config.time_zone = 'UTC' to environment.rb"
  end
  key_timestamp = Time.now.utc
  record.send :write_attribute, key_timestamp_field, key_timestamp
  key
end
invariants_satisfied?() click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 222
def invariants_satisfied?
  self.class.invariants.all? { |i| record.instance_eval(&i) }
end
key() click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 200
def key
  require 'digest/sha1'
  timestamp = record.read_attribute(key_timestamp_field)
  if timestamp
    timestamp = timestamp.getutc
    Digest::SHA1.hexdigest("#{record.id}-#{state_name}-#{timestamp}-#{Rails.application.config.secret_token}")
  end
end
key_expired?() click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 209
def key_expired?
  timestamp = record.read_attribute(key_timestamp_field)
  timestamp.nil? || (timestamp.getutc + key_timeout < Time.now.utc)
end
key_timeout() click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 186
def key_timeout
  record.class::Lifecycle.options[:key_timeout]
end
key_timestamp_field() click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 182
def key_timestamp_field
  record.class::Lifecycle.options[:key_timestamp_field]
end
method_missing(name, *args) click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 231
def method_missing(name, *args)
  if name.to_s =~ /^(.*)_in_progress\?$/
    active_step_is?($1)
  else
    super
  end
end
publishable_transitions_for(user) click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 151
def publishable_transitions_for(user)
  record.with_acting_user(user) do
    available_transitions_for(user).select do |t|
      t.publishable_by(user, t.available_to, record)
    end
  end
end
state() click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 132
def state
  self.class.states[state_name]
end
state_name() click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 126
def state_name
  name = record.read_attribute(self.class.state_field)
  name.to_sym if name
end
transition(name, user, attributes) click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 115
def transition(name, user, attributes)
  transition = find_transition(name, user) or raise LifecycleError, "No transition #{name} available"
  transition.run!(record, user, attributes)
end
valid_key?() click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 214
def valid_key?
  provided_key && provided_key == key && !key_expired?
end

Public Class Methods

can_create?(name, user) click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 78
def self.can_create?(name, user)
  creators[name.to_sym].allowed?(user)
end
create(name, user, attributes=nil) click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 83
def self.create(name, user, attributes=nil)
  creator = creators[name.to_sym] or raise LifecycleError, "No creator #{name} available"
  creator.run!(user, attributes)
end
creator(name) click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 73
def self.creator(name)
  creators[name.to_sym] or raise ArgumentError, "No such creator in lifecycle: #{name}"
end
def_creator(name, on_create, options) click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 32
def self.def_creator(name, on_create, options)
  class_eval %Q{
               def self.#{name}(user, attributes=nil)
                 create(:#{name}, user, attributes)
               end
               def self.can_#{name}?(user, attributes=nil)
                 can_create?(:#{name}, user)
               end
              }
  Creator.new(self, name.to_s, on_create, options)
end
def_state(name, on_enter) click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 25
def self.def_state(name, on_enter)
  name = name.to_sym
  class_eval "def #{name}_state?; state_name == :#{name} end"
  states[name] = Lifecycles::State.new(name, on_enter)
end
def_transition(name, start_states, end_state, on_transition, options) click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 44
def self.def_transition(name, start_states, end_state, on_transition, options)
  class_eval %Q{
               def #{name}!(user, attributes=nil)
                 transition(:#{name}, user, attributes)
               end
               def can_#{name}?(user, attributes=nil)
                 can_transition?(:#{name}, user)
               end
              }
  Transition.new(self, name.to_s, start_states, end_state, on_transition, options)
end
init(model, options) click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 7
def self.init(model, options)
  @model   = model
  @options = options
  reset
end
key_timeout() click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 93
def self.key_timeout
  options[:key_timeout]
end
new(record) click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 105
def initialize(record)
  @record = record
end
publishable_creators() click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 60
def self.publishable_creators
  creators.values.where.publishable?
end
publishable_transitions() click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 64
def self.publishable_transitions
  transitions.where.publishable?
end
reset() click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 13
def self.reset
  @states        = {}
  @creators      = {}
  @transitions   = []
  @invariants    = []
end
state_field() click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 89
def self.state_field
  options[:state_field]
end
state_names() click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 56
def self.state_names
  states.keys
end
step_names() click to toggle source
# File lib/hobo/model/lifecycles/lifecycle.rb, line 68
def self.step_names
  (creators.keys | transitions.*.name).uniq
end