GitHub User: rdpoor
Late to the party -- I like Ryan's approach but was troubled by the complexity of the create() method. My modified approach has a Wizard model that saves the current_step as a db field (so it's preserved across sessions) and saves an instance before starting. From there, everything is done in the upate() method, so the controller simplifies down to:
(params[:step] == 'back') ? @wizard.step_back : @wizard.step_forward
redirect_to wizard_path, :notice => 'update succeeded'
# the reload restores the previous (valid) step as the current step
The only other substantive change is the next / prev buttons in the views, which might look like this:
<%= form_for(@wizard, :url => wizard_path, :method => :put) do |f| %>
<%= render 'show_errors' %>
<%= f.label :address %>: <%= f.text_field :address %><br />
<%= f.submit "back", :name => 'step' unless @wizard.first_step? %>
<%= f.submit "next", :name => 'step' unless @wizard.last_step? %>
<% end %>
Ryan (or anyone): One question: The client is effectively doing a GET, right? And GETs are supposed to be idempotent (not change the state on the server). Do you have to do anything special to tell the server's cacheing mechanisms that a GET on the same URI twice in a row might yield different results? Or is it just luck that the &after= query parameter has that effect (since it changes continually)?