Created
June 2, 2010 18:32
-
-
Save ismasan/422777 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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