All pastes #23559 Raw Edit

sequenced.rb

public ruby v1 · immutable
#23559 ·published 2005-09-21 21:51 UTC
rendered paste body
# originally at http://www.opendbms.com/sequenced.rb# author Jeffrey Moss (zardinuk on IRC)module Sequenced  module SequencedClass    # USAGE: in your class definitions, you can manipulate the sequence array    #    # class Product < ActionController::Base    #   include Sequenced    #    #   sequence.push {'customer_information' => proc { @order.legal_entity.nil? }},    #                 {'billing_information'  => proc { @order.billing_address.nil? }}    #    #   def customer_information    #     ...    #   end    #    #   def billing_information    #     ...    #   end    # end    #    # class PhoneProduct < Product    #   sequence.insert 0, {'product_selection' => TRUE } # ask this first!    #   sequence.push {'phone_lines' => proc { @order.phone_lines.empty? }    #    #   def product_selection    #     if @request.post?    #       @product = @params['product']    #       redirect_to next_action # next_action is defined by Sequenced    #     end    #   end    # end    #    # The purpose of the mixin is to allow you to easily determin the next    # action in a complex string of events, and to be able to embed that anywhere    # a url_for, redirect_to, link_to, form_tag any of that, and eliminate the    # maintenance of a giant linked list, to make adding a new action somewhere    # much easier.    # You can also manually set a next_action in your flash['next_action'] which    # functions as a return page, for instance, if you want to return to the same    # page they were at before authentication was required. Also pass next_action    # in as a parameter, in a hidden form element for example, which is more    # robust than putting it in flash    attr_accessor :sequence    def inherited(subclass)      super      subclass.sequence = sequence.clone # each subclass has a new copy of the sequence    end  end  class << self    def append_features(incoming)      super      incoming.extend SequencedClass      incoming.sequence = []    end  end  # instance methods  def next_action    action = action_name    return @next_action ||= @params['next_action'] || flash['next_action'] || begin      action = process_sequence_action(                 self.class.sequence[ (self.class.sequence.index(action) || -1) + 1 ]               )    end while (action.nil?)  end  def previous_action    action = action_name    return @previous_action ||= begin      action = process_sequence_action(                 self.class.sequence[ (self.class.sequence.index(action) || -2) - 1 ]               )    end while (action.nil?)  end  private  def process_sequence_action(action)    action.each do |action_name, conditions|      # TODO: should be able to support different operations by returning      #  symbols other than true/false, like :action, :controller, :skip, stuff like that      case conditions      when Proc        return {:action => action_name} if instance_eval &conditions #evaluates in current context      when String        return {:action => action_name} if instance_eval conditions      else        return {:action => action_name} if conditions      end      break # loop only runs once    end  endend