RailsCasts Pro episodes are now free!

Learn more or hide this

Robert Poor's Profile

GitHub User: rdpoor

Comments by Robert Poor

Avatar

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:

ruby
  def show
    render @wizard.current_step
  end

  def update
    (params[:step] == 'back') ? @wizard.step_back : @wizard.step_forward
    if @wizard.update_attributes(params[:wizard])
      redirect_to wizard_path, :notice => 'update succeeded'
    else
      # the reload restores the previous (valid) step as the current step
      render @wizard.reload.current_step
    end
  end

The only other substantive change is the next / prev buttons in the views, which might look like this:

ruby
<%= form_for(@wizard, :url => wizard_path, :method => :put) do |f| %>
  <%= render 'show_errors' %>
  <div class="field">
    <%= f.label :address %>: <%= f.text_field :address %><br />
  </div>
  <div class="actions">
    <%= f.submit "back", :name => 'step' unless @wizard.first_step? %>
    <%= f.submit "next", :name => 'step' unless @wizard.last_step? %>
  </div>
<% end %>
Avatar

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)?