Skip to content

Instantly share code, notes, and snippets.

@ismasan
Created June 2, 2010 18:32
Show Gist options
  • Save ismasan/422777 to your computer and use it in GitHub Desktop.
Save ismasan/422777 to your computer and use it in GitHub Desktop.
# Quick spike for a multi-page presenter configurator (intended for Rails apps)
# Create you own presenters with validation (one per page). Use this module to configure the sequence of steps (pages)
require File.dirname(__FILE__) + '/../config/environment'
module Wizard
class UnknownStepError < ArgumentError;end
class InvalidStepError < StandardError;end
@@sequences = {}
def self.define(key, &block)
@@sequences[key] = (
seq = Sequence.new
seq.instance_eval &block
seq.after_configure
seq
)
end
def self.[](key)
@@sequences[key]
end
class Sequence
attr_reader :previous_step, :steps
def initialize
@steps = []
@suffix = 'Presenter'
end
def after_configure
@previous_step = @steps.first
end
def suffix(s)
@suffix = s.to_s.classify
end
def step(step_name)
@steps << step_name
end
def present!(step_name, *args)
step_name = step_name.to_sym
raise UnknownStepError unless @steps.include?(step_name)
index = @steps.index(step_name)
presenter = if index == 0 # first step.
instance(step_name, args)
else
prev = instance(@steps[index - 1], args)
if !prev.valid?
@previous_step = @steps[index - 1]
raise InvalidStepError
end
instance(step_name, args)
end
end
protected
def instance(step_name, args)
"#{step_name}#{@suffix}".classify.constantize.new(*args)
end
end
end
# EXAMPLE USAGE ######################################
# Configure wizard
Wizard.define(:orders) do
suffix 'presenter'
step :starting
step :billing
step :confirming
step :complete
end
wizard = Wizard[:orders]
# Your own presenters. Must implement valid?
class StartingPresenter
def initialize(one, two, three)
@one, @two, @three = one, two, three
end
def inspect
"#{self.class.name}: #{object_id}: #{@one}, #{@two}, #{@three}"
end
def valid?
true
end
end
class BillingPresenter < StartingPresenter
def valid?
false
end
end
class ConfirmingPresenter < StartingPresenter
def valid?
true
end
end
# In controllers, show action
begin
presenter = wizard.present!(:confirming, 1, 2, 3) # 1, 2, 3 are whatever arguments presenter expects
puts "Using presenter #{presenter.inspect}"
rescue Wizard::InvalidStepError => boom
puts "Cannot present this stage"
puts "Redirecting to #{wizard.previous_step}" # => :starting
end
# Controller, POST or PUT actions
# presenter = presenter = wizard.present!(:confirming, 1, 2, 3)
# if presenter.save
# redirect
# else
# render :action => presenter_template
# end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment