Agile Web Development with Rails, Edition 4
11.2 Iteration F2: Creating an AJAX-Based Cart
10.4 Playtime
11.1 Iteration F1: Moving the Cart
<Your Cart> expected but was
<11.1 Iteration F1: Moving the Cart>.
<0> expected to be
>=
<1>.
Traceback:
/home/rubys/git/awdwr/edition4/checkdepot.rb:209:in `block in <class:DepotTest>'
Refactor the cart view into partials, and reference the result from the layout.
Create a "partial" view, for just one line item
edit app/views/line_items/_line_item.html.erb
<tr>
<td><%= line_item.quantity %>×</td>
<td><%= line_item.product.title %></td>
<td class="item_price"><%= number_to_currency(line_item.total_price) %></td>
</tr>
Replace that portion of the view with a callout to the partial
edit app/views/carts/show.html.erb
<% if notice %>
<p id="notice"><%= notice %></p>
<% end %>
<h2>Your Cart</h2>
<table>
<%= render(@cart.line_items) %>
<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?' } %>
Make a copy as a partial for the cart controller
cp app/views/carts/show.html.erb app/views/carts/_cart.html.erb
Modify the copy to reference the (sub)partial and take input from @cart
edit app/views/carts/_cart.html.erb
<h2>Your Cart</h2>
<table>
<%= render(cart.line_items) %>
<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?' } %>
Keep things DRY
edit app/views/carts/show.html.erb
<% if notice %>
<p id="notice"><%= notice %></p>
<% end %>
<%= render @cart %>
Reference the partial from the layout.
edit app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
<head>
<title>Pragprog Books Online Store</title>
<%= stylesheet_link_tag "application", media: "all",
"data-turbolinks-track" => true %>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
<%= csrf_meta_tags %>
</head>
<body class="<%= controller.controller_name %>">
<div id="banner">
<%= image_tag("logo.png") %>
<%= @page_title || "Pragmatic Bookshelf" %>
</div>
<div id="columns">
<div id="side">
<div id="cart">
<%= render @cart %>
</div>
<ul>
<li><a href="http://www....">Home</a></li>
<li><a href="http://www..../faq">Questions</a></li>
<li><a href="http://www..../news">News</a></li>
<li><a href="http://www..../contact">Contact</a></li>
</ul>
</div>
<div id="main">
<%= yield %>
</div>
</div>
</body>
</html>
Insert a call in the controller to find the cart
edit app/controllers/store_controller.rb
class StoreController < ApplicationController
include CurrentCart
before_action :set_cart
def index
@products = Product.order(:title)
end
end
Add a small bit of style.
edit app/assets/stylesheets/carts.css.scss
.carts, #side #cart {
.item_price, .total_line {
text-align: right;
}
.total_line .total_cell {
font-weight: bold;
border-top: 1px solid #595;
}
}
edit app/assets/stylesheets/application.css.scss
#side {
float: left;
padding: 1em 2em;
width: 13em;
background: #141;
form, div {
display: inline;
}
input {
font-size: small;
}
#cart {
font-size: smaller;
color: white;
table {
border-top: 1px dotted #595;
border-bottom: 1px dotted #595;
margin-bottom: 10px;
}
}
ul {
padding: 0;
li {
list-style: none;
a {
color: #bfb;
font-size: small;
}
}
}
}
Change the redirect to be back to the store.
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 store_url }
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
Purchase another product.
get /
Getting started
Here’s how to get rolling:
-
Use bin/rails generate
to create your models and controllers
To see all available options, run it without parameters.
-
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.
-
Configure your database
If you're not using SQLite (the default), edit config/database.yml with your username and password.
11.2 Iteration F2: Creating an AJAX-Based Cart
10.4 Playtime