module StatusWorkflow::ClassMethods

Public Instance Methods

before_status_transition(&blk) click to toggle source
# File lib/status_workflow.rb, line 86
def before_status_transition(&blk)
  @before_status_transition = blk
end
status_workflow(workflows) click to toggle source
# File lib/status_workflow.rb, line 89
def status_workflow(workflows)
  if workflows.first.last.is_a?(Array)
    # default mode: use just status
    workflows = { nil => workflows }
  end
  workflows.each do |prefix, transitions|
    if prefix
      # no this is not a mistake, the localvar is prefix_
      prefix_ = "#{prefix}_"
      define_method "#{prefix_}status_transition!" do |*args, &blk|
        status_transition!(*(args+[prefix]), &blk)
      end
    end
    transitions.inject({}) do |memo, (from_status, to_statuses)|
      to_statuses.each do |to_status|
        to_status = to_status.to_sym
        memo[to_status] ||= Set.new
        memo[to_status] << from_status&.to_sym # support nil or strings/symbols
      end
      memo
    end.each do |to_status, from_statuses|
      define_method "#{prefix_}enter_#{to_status}!" do
        send "#{prefix_}status_transition!", nil, to_status
      end
      define_method "#{prefix_}can_enter_#{to_status}?" do |raise_error = false|
        reload
        status = read_attribute "#{prefix_}status"
        memo = from_statuses.include? status&.to_sym
        if raise_error and not memo
          raise InvalidTransition, "can't enter #{to_status} from #{status}, expected #{from_statuses.to_a.join('/')}"
        end
        memo
      end
      define_method "#{prefix_}enter_#{to_status}_if_possible" do
        begin; send("#{prefix_}enter_#{to_status}!"); rescue InvalidTransition; false; end
      end
    end
  end
end