4

I've been trying to create an order confirmation page for my rails app, and am not quite sure how to go about it in a restful way.

There were a few answers on this question that got me halfway there, but the problem was that I wasn't quite sure how to set up the form in the rails view so that it would take the user to a confirmation page with all their details instead of a create action.

Right now my view is simple:

        <% form_for :order do |f| %>
      <%= f.error_messages %>
      <p>
        <%= f.label :first_name %><br />
        <%= f.text_field :first_name, :size => 15 %>
      </p>
      <p>
        <%= f.label :last_name %><br />
        <%= f.text_field :last_name, :size => 15 %>
      </p>
      (Be sure to enter your name as it appears on your card)
      <p>
        <%= f.label :card_type %><br />
        <%= f.select :card_type, [["Visa", "visa"], ["MasterCard", "master"], ["Discover", "discover"], ["American Express", "american_express"]] %>
      </p>
      <p>
        <%= f.label :card_number %><br />
        <%= f.text_field :card_number %>
      </p>
      <p>
        <%= f.label :card_verification, "Card Verification Value (CVV)" %><br />
        <%= f.text_field :card_verification, :size => 3 %>
      </p>
      <p>
        <%= f.label :card_expires_on %><br />
        <%= f.date_select :card_expires_on, :discard_day => true, :start_year => Date.today.year, :end_year => (Date.today.year+10), :add_month_numbers => true %>
      </p>
  <p><%= f.submit "Submit" %></p>

What things should I be doing to direct the user to a confirmation page that shows all the order details?

Thanks!

Kenji

Community
  • 1
  • 1
Kenji Crosland
  • 2,914
  • 6
  • 31
  • 40

3 Answers3

10

There were a few answers on this question that got me halfway there, but the problem was that I wasn't quite sure how to set up the form in the rails view so that it would take the user to a confirmation page with all their details instead of a create action.

Directing a form to a non standard page is pretty simple.

Add a url option form_for. Such that

<% form_for :order do |f| %>

becomes

<% form_for :order :url => {:action => "confirm"} do |f| %>

You'll need to crate the confirm action in your routes, but that only involves this:

map.resources :orders, :collection => {:confirm => :get}

All you need now is a basic controller action and a view:

def confirm
  @order = Order.new(params[:order])
  unless @order.valid?
    render :action => :new
  else       
  end
end

Your view should look almost identical to the show view, with the addition of a form submitting @order to the create action.

EmFi
  • 23,435
  • 3
  • 57
  • 68
  • This almost works. The problem seems to be the credit card number and expiration date. These numbers aren't stored in the order object and are sent directly to the payment gateway. In the model I have this: attr_accessor :card_number, :card_verification These attributes don't seemed to be picked up on the confirmation page when I click submit. – Kenji Crosland Dec 14 '09 at 23:11
  • If they're defined as attr\_accessors on Order. They should be available in the confirmation view. – EmFi Dec 14 '09 at 23:28
  • It seems to work if I have another form that looks identical to the one in the "new" action, but in this case I'd like to just render text with the order info with a link to "Edit this order" to go back to the new action. – Kenji Crosland Dec 14 '09 at 23:44
  • It should also work if you adapt the view to access order.card_number, etc. Might want to star out some of those values as they go to screen. The hidden form on the confirmation page should contain all the information that the new order page does. – EmFi Dec 15 '09 at 00:04
  • Problem solved with a hidden div for the form. Thanks for getting me started Emfi! – Kenji Crosland Dec 15 '09 at 00:07
2

Why don't you pull the confirmation via ajax for example, pull the result and put it as an overlay div, upon confirmation submit the original values in the form.

If you still need to do it your way then check wizardly, it's exactly designed for such uses.

khelll
  • 23,590
  • 15
  • 91
  • 109
0

I would like to update the answer for more elegant Rails 4 or up. I hope it will help newbies like me. Ruby is awesome! :)

routes.rb

resources :orders do
  collection do
    post 'confirm'
  end
 end

orders_controller.rb

def confirm
  @order = Order.new(order_params) # GET THE POST parameters
  render :new if @order.invalid? # Return if false
end

form.html.erb

<%= form_for @order, url: {action: 'confirm'} do |f| %>
d_dnara
  • 49
  • 1
  • 5