views:

279

answers:

1

I have a form that, on submit, requires the customer to look over the data, and then confirm the changes before saving the data.

However, I'm using a really rough way of retaining data if the user hits the back button to go back and look over the data before submitting. Since I want the user's updates to the fields and not the current database fields, to be what displays on this "go back" action, I have to pass the values around via post/get params. So my controller looks something like:

    @customer = Customer.find session[:id]
 unless params[:customer].nil?
  @customer.attributes = params[:customer]
 end

Is there a better way to do this? I'm actually really curious what the generally accepted Rails session usage is as I'm pretty sure using the session for passing info like this is taboo. Yes, no? Thoughts? Thanks.

A: 

There may be a better way to do it involving sessions. I would rather avoid using the session hash entirely, with a second form and a lot of javascript.

Here's how I'd handle it. The first form wouldn't change much at all, just submit to a new action called review.

The review action will display the changes for review, and have an edit link and a confirm button visible. It will also recreate the form from the previous page in a hidden element which will submit again to the review action.

The confirm button would submit to your update action.

Clicking the edit link will hide the review area and show duplicated from from the previous page.

Here's some sample code to hammer down the point:

app/controllers/example_controller.rb

class ExampleController < ApplicationController

  def edit
    @example = Example.find(params[:id])
  end

  def review
    @example = Example.find(params[:id])
    @example.update_attributes(params[:example])
    @example.valid?
  end

  def update
    @example = Example.find(params[:id])
    @example.update_attributes(params[:example])
    if @example.save
      redirect_to @example
    else
      render :action => :review
    end
  end
end

app/views/examples/_form.html.erb:

<% form_form @example, :url => {:action => "review"} do |f|%>
  ...
    Form inputs go here
  ...
<% end %>

app/views/examples/edit.html.erb:

 <%= render :parital => form %>

app/views/examples/review.html.erb:

 <div id="review">
   ...
     content for review goes here
   ...
   <%= link_to_function "Edit", "$('review').hide(); $('edit').show()"
   <% form_for @example do |f| %>
     <%= hidden_field :attribute, @example.attribute %>
     ...
       hidden_field for each attribute
     ...
     <%= submit_tag "Accept These Changes" %>
   <% end %>
 </div>
 <div id="edit" style="display:none">
   <%= render :partial => 'form' %>
 </div>
EmFi
so are would your show hidden elements using ajax/javascript or are these full page redirects?
Lukas
I thought I was being clear, in that it was just Javascript, but I guess not. I've added an example to my answer.
EmFi
I feel like you could get away with just the review.erb, and have the "edit" div displaying first, then when you hit the "submit", it hides itself and displays the review form. Thats just an observation though.I'm more curious though how to do this if I was to do it without javascript. Even if I were to use JS, I'd want to be JS-disabled compatible. While I agree, this is an easy way to do it, I'm not sure I can do it *only* this way.
Lukas
I think it could just involve the two forms "edit" and the hidden fields "review". And allow them to post back and forth. One solution I'm doing is here: http://gist.github.com/232161
Lukas
The problem with submitting to javascript is that validation errors won't be caught until sent to the confirmation action. The method I described can easily be made to fall back to javascript, by making the edit link go back to the edit page given the form as parameters.
EmFi
I like this solution for that reason (and am already doing something like this in other projects). To work around the above issue, you can simply have that page redirect back to the previous page if there are validation errors on submit with a flash message. I do like the JS solution, don't get me wrong. Just trying to see if there are other low-impact, non-js workarounds.
Lukas