First in store_controller.rb, remove save_order action, and replace checkout action with following code:
def checkout if params[:order] @order = Order.new(params[:order]) @order.add_line_items_from_cart(@cart) if @order.save session[:cart] = nil redirect_to_index("Thank you for your order") else render :action => :checkout end else if @cart.items.empty? redirect_to_index("Your cart is empty") else @order = Order.new end end end
And then in the checkout.rhtml, simply edit the form_for start tag from:
<% form_for :order, :url => {:action => :save_order } do |form| %>
to:
<% form_for :order do |form| %>
Alternatively since we already have the code to save an order in save_order we could just call it like this:
def checkout if params[:order] save_order else if @cart.items.empty? redirect_to_index("Your cart is empty") else @order = Order.new end end end
Marcello:
Well, first I would change the butto_to from the cart partial to
<%= button_to "Checkout", {:action => :checkout}, {:method => :get} if @order.nil?%>
It will ensure that the clicking of this button will call the action using a the get method, just to render the order form.
On the checkout, just change the form_for tag to:
<% form_for :order do |f| %>
The checkout then a quick and really dirty hack in the checkout method
def checkout if request.post? @order = Order.new(params[:order]) @order.add_line_items_from_cart(@cart) if @order.save session[:cart] = nil redirect_to_index("Thank you for your order") end elsif @cart.items.empty? redirect_to_index("Your cart is empty") else @order = Order.new end end
That way it will check for the type of request, creating the @order object and saving it, otherwise it behaves like the old checkout method.
linoj:
I'd put the test for empty cart first, since you dont want to check out at all if its empty; then the elsif's
Derick Ng:
For minimal changes, here is what I did (you definitely need the change to checkout.rhtml as well). I did not change the Checkout button to use GET so I added a check for params. I guess it is always good to check.
def checkout @order = Order.new(params[:order]) if @cart.items.empty? redirect_to_index("Your cart is empty") elsif request.post? and params[:order] @order.add_line_items_from_cart(@cart) if @order.save session[:cart] = nil redirect_to_index("Thank you for your order") else render :action => :checkout end end end
Martin:
action in controller (form will need to postback):
def checkout if @cart.items.empty? redirect_to_index('Your cart is empty') else @order = Order.new(params[:order]) if request.post? && params[:order] @order.add_line_items_from_cart(@cart) if @order.save session[:cart] = nil redirect_to_index('Thank you for your order') end end end end
change to checkout form (checkout.rhtml, no action specified, so the from postsback to action which invoked it, i.e. checkout):
<% form_for :order do |order| %>
and of course the checkout button in _cart shouldn't be displayed on the checkout page:
<%= button_to "Checkout", {:action => :checkout} unless (request.request_uri == '/store/checkout') %>