Agile Web Development with Rails, Edition 4

10.4 Playtime 10.2 Iteration E2: Handling Errors

10.3 Iteration E3: Finishing the Cart

Expected at least 1 element matching "#notice", found 0.
<0> expected to be
>=
<1>.

Traceback:
  /home/rubys/git/awdwr/edition4/checkdepot.rb:188:in `block in <class:DepotTest>'

Add empty cart button, remove flash for line item create, add totals to view.

Add button to the view.

edit app/views/carts/show.html.erb
<% if notice %>
<p id="notice"><%= notice %></p>
<% end %>
 
<h2>Your Pragmatic Cart</h2>
<ul>    
  <% @cart.line_items.each do |item| %>
    <li><%= item.quantity %> &times; <%= item.product.title %></li>
  <% end %>
</ul>
 
<%= button_to 'Empty cart', @cart, method: :delete,
    data: { confirm: 'Are you sure?' } %>

Clear session and change flash notice when cart is destroyed.

edit app/controllers/carts_controller.rb
  def destroy
    @cart.destroy if @cart.id == session[:cart_id]
    session[:cart_id] = nil
    respond_to do |format|
      format.html { redirect_to store_url,
        notice: 'Your cart is currently empty' }
      format.json { head :no_content }
    end
  end

Try it out.

get /carts/1

ActiveRecord::RecordNotFound in CartsController#show

Couldn't find Cart with 'id'=1

Extracted source (around line #85):
83
84
85
86
87
88
              
#END:setup# Use callbacks to share common setup or constraints between actions.
def set_cart
@cart = Cart.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.

Rails.root: /home/rubys/git/awdwr/edition4/work-230/depot

Application Trace | Framework Trace | Full Trace

Request

Parameters:

{"id"=>"1"}

Response

Headers:

None

Remove scaffolding generated flash notice for line item create.

edit app/controllers/line_items_controller.rb
  def create
    product = Product.find(params[:product_id])
    @line_item = @cart.add_product(product.id)
 
    respond_to do |format|
      if @line_item.save
        format.html { redirect_to @line_item.cart }
        format.json { render :show,
          status: :created, location: @line_item }
      else
        format.html { render :new }
        format.json { render json: @line_item.errors,
          status: :unprocessable_entity }
      end
    end
  end

Update the view to add totals.

edit app/views/carts/show.html.erb
<% if notice %>
<p id="notice"><%= notice %></p>
<% end %>
 
<h2>Your Cart</h2>
<table>
  <% @cart.line_items.each do |item| %>
    <tr>
      <td><%= item.quantity %>&times;</td>
      <td><%= item.product.title %></td>
      <td class="item_price"><%= number_to_currency(item.total_price) %></td>
    </tr>
  <% end %>
 
  <tr class="total_line">
    <td colspan="2">Total</td>
    <td class="total_cell"><%= number_to_currency(@cart.total_price) %></td>
  </tr>
 
</table>
 
<%= button_to 'Empty cart', @cart, method: :delete,
    data: { confirm: 'Are you sure?' } %>

Add a method to compute the total price of a single line item.

edit app/models/line_item.rb
 
  def total_price
    product.price * quantity
  end

Add a method to compute the total price of the items in the cart.

edit app/models/cart.rb
  def total_price
    line_items.to_a.sum { |item| item.total_price }
  end

Add some style.

edit app/assets/stylesheets/carts.css.scss
 
 
.carts {
  .item_price, .total_line {
    text-align: right;
  }
 
  .total_line .total_cell {
    font-weight: bold;
    border-top: 1px solid #595;
  }
}

Add a product to the cart, and see the total.

get /

Getting started

Here’s how to get rolling:

  1. Use bin/rails generate to create your models and controllers

    To see all available options, run it without parameters.

  2. Set up a root route to replace this page

    You're seeing this page because you're running in development mode and you haven't set a root route yet.

    Routes are set up in config/routes.rb.

  3. Configure your database

    If you're not using SQLite (the default), edit config/database.yml with your username and password.

Add a few more products, and watch the totals climb!

10.4 Playtime 10.2 Iteration E2: Handling Errors