Task F: Administration #1

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') %>
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License