13 Task I: Internationalization 11.4 Iteration F4: Adding a Sidebar, More Administration
edit app/models/product.rb
class Product < ActiveRecord::Base
has_many :orders, :through => :line_items
has_many :line_items
# ...
rails generate controller info who_bought
create app/controllers/info_controller.rb
route get "info/who_bought"
invoke erb
create app/views/info
create app/views/info/who_bought.html.erb
invoke test_unit
create test/functional/info_controller_test.rb
invoke helper
create app/helpers/info_helper.rb
invoke test_unit
create test/unit/helpers/info_helper_test.rb
edit app/controllers/info_controller.rb
class InfoController < ApplicationController
def who_bought
@product = Product.find(params[:id])
@orders = @product.orders
respond_to do |format|
format.xml { render :layout => false }
end
end
protected
def authorize
end
end
edit app/views/info/who_bought.xml.builder
xml.order_list(:for_product => @product.title) do
for o in @orders
xml.order do
xml.name(o.name)
xml.email(o.email)
end
end
end
curl --silent http://localhost:3000/info/who_bought/3
<order_list for_product="Pragmatic Version Control">
<order>
<name>Dave Thomas</name>
<email>customer@example.com</email>
</order>
</order_list>
curl --silent http://localhost:3000/info/who_bought/3
<order_list for_product="Pragmatic Version Control">
<order>
<name>Dave Thomas</name>
<email>customer@example.com</email>
</order>
</order_list>
sqlite3> select * from products
id = 2
title = Pragmatic Project Automation
description = <p>
<em>Pragmatic Project Automation</em> shows you how to improve the
consistency and repeatability of your project's procedures using
automation to reduce risk and errors.
</p>
<p>
Simply put, we're going to put this thing called a computer to work
for you doing the mundane (but important) project stuff. That means
you'll have more time and energy to do the really
exciting---and difficult---stuff, like writing quality code.
</p>
image_url = /images/auto.jpg
created_at = 2012-06-29 19:11:41.032049
updated_at = 2012-06-29 19:11:41.032049
price = 29.95
id = 3
title = Pragmatic Version Control
description = <p>
This book is a recipe-based approach to using Subversion that will
get you up and running quickly---and correctly. All projects need
version control: it's a foundational piece of any project's
infrastructure. Yet half of all project teams in the U.S. don't use
any version control at all. Many others don't use it well, and end
up experiencing time-consuming problems.
</p>
image_url = /images/svn.jpg
created_at = 2012-06-29 19:11:41.043500
updated_at = 2012-06-29 19:11:41.043500
price = 28.5
id = 4
title = Pragmatic Unit Testing (C#)
description = <p>
Pragmatic programmers use feedback to drive their development and
personal processes. The most valuable feedback you can get while
coding comes from unit testing.
</p>
<p>
Without good tests in place, coding can become a frustrating game of
"whack-a-mole." That's the carnival game where the player strikes at a
mechanical mole; it retreats and another mole pops up on the opposite side
of the field. The moles pop up and down so fast that you end up flailing
your mallet helplessly as the moles continue to pop up where you least
expect them.
</p>
image_url = /images/utc.jpg
created_at = 2012-06-29 19:11:41.048112
updated_at = 2012-06-29 19:11:41.048112
price = 27.75
sqlite3> select * from line_items
id = 1
product_id = 3
order_id = 1
quantity = 1
total_price = 28.5
created_at = 2012-06-29 19:12:46.942016
updated_at = 2012-06-29 19:12:46.942016
curl --silent http://localhost:3000/info/who_bought/3
<order_list for_product="Pragmatic Version Control">
<order>
<name>Dave Thomas</name>
<email>customer@example.com</email>
</order>
</order_list>
edit app/views/info/who_bought.html.erb
<h3>People Who Bought <%= @product.title %></h3>
<ul>
<% for order in @orders -%>
<li>
<%= mail_to order.email, order.name %>
</li>
<% end -%>
</ul>
edit app/controllers/info_controller.rb
class InfoController < ApplicationController
def who_bought
@product = Product.find(params[:id])
@orders = @product.orders
respond_to do |format|
format.html
format.xml { render :layout => false }
end
end
protected
def authorize
end
end
curl --silent -H "Accept: text/html" http://localhost:3000/info/who_bought/3
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!-- START:jit -->
<html>
<head>
<title>Pragprog Books Online Store</title>
<!-- START:stylesheet -->
<link href="/stylesheets/depot.css?1340997161" media="all" rel="stylesheet" type="text/css" />
<!-- END:stylesheet -->
<script src="/javascripts/prototype.js?1340997034" type="text/javascript"></script>
<script src="/javascripts/effects.js?1340997034" type="text/javascript"></script>
<script src="/javascripts/dragdrop.js?1340997034" type="text/javascript"></script>
<script src="/javascripts/controls.js?1340997034" type="text/javascript"></script>
<script src="/javascripts/rails.js?1340997034" type="text/javascript"></script>
<script src="/javascripts/application.js?1340997034" type="text/javascript"></script>
</head>
<!-- END:jit -->
<body id="store">
<div id="banner">
<img alt="Logo" src="/images/logo.png?1340997101" />
Pragmatic Bookshelf
</div>
<div id="columns">
<div id="side">
<!-- START:hidden_div -->
<!-- START_HIGHLIGHT -->
<!-- END_HIGHLIGHT -->
<!-- END:hidden_div -->
<a href="http://www....">Home</a><br />
<a href="http://www..../faq">Questions</a><br />
<a href="http://www..../news">News</a><br />
<a href="http://www..../contact">Contact</a><br />
<!-- START_HIGHLIGHT -->
<!-- END_HIGHLIGHT -->
</div>
<div id="main">
<!-- START:flash -->
<!-- END:flash -->
<h3>People Who Bought Pragmatic Version Control</h3>
<ul>
<li>
<a href="mailto:customer@example.com">Dave Thomas</a>
</li>
</ul>
</div>
</div>
</body>
</html>
curl --silent -H "Accept: application/xml" http://localhost:3000/info/who_bought/3
<order_list for_product="Pragmatic Version Control">
<order>
<name>Dave Thomas</name>
<email>customer@example.com</email>
</order>
</order_list>
cp app/controllers/info_controller.rb app/controllers/info_controller.save
edit app/controllers/info_controller.rb
class InfoController < ApplicationController
def who_bought
@product = Product.find(params[:id])
@orders = @product.orders
respond_to do |format|
format.html
format.xml { render :layout => false ,
:xml => @product.to_xml(:include => :orders) }
end
end
protected
def authorize
end
end
curl --silent http://localhost:3000/info/who_bought/3.xml
<?xml version="1.0" encoding="UTF-8"?>
<product>
<price type="decimal">28.5</price>
<created-at type="datetime">2012-06-29T19:11:41Z</created-at>
<image-url>/images/svn.jpg</image-url>
<title>Pragmatic Version Control</title>
<updated-at type="datetime">2012-06-29T19:11:41Z</updated-at>
<id type="integer">3</id>
<description><p>
This book is a recipe-based approach to using Subversion that will
get you up and running quickly---and correctly. All projects need
version control: it's a foundational piece of any project's
infrastructure. Yet half of all project teams in the U.S. don't use
any version control at all. Many others don't use it well, and end
up experiencing time-consuming problems.
</p></description>
<orders type="array">
<order>
<address>123 Main St</address>
<name>Dave Thomas</name>
<created-at type="datetime">2012-06-29T19:12:46Z</created-at>
<updated-at type="datetime">2012-06-29T19:12:46Z</updated-at>
<pay-type>check</pay-type>
<id type="integer">1</id>
<email>customer@example.com</email>
</order>
</orders>
</product>
edit app/views/info/who_bought.atom.builder
atom_feed do |feed|
feed.title "Who bought #{@product.title}"
feed.updated @orders.first.created_at
for order in @orders
feed.entry(order) do |entry|
entry.title "Order #{order.id}"
entry.summary :type => 'xhtml' do |xhtml|
xhtml.p "Shipped to #{order.address}"
xhtml.table do
xhtml.tr do
xhtml.th 'Product'
xhtml.th 'Quantity'
xhtml.th 'Total Price'
end
for item in order.line_items
xhtml.tr do
xhtml.td item.product.title
xhtml.td item.quantity
xhtml.td number_to_currency item.total_price
end
end
xhtml.tr do
xhtml.th 'total', :colspan => 2
xhtml.th number_to_currency \
order.line_items.map(&:total_price).sum
end
end
xhtml.p "Paid by #{order.pay_type}"
end
entry.author do |author|
entry.name order.name
entry.email order.email
end
end
end
end
edit app/controllers/info_controller.rb
class InfoController < ApplicationController
def who_bought
@product = Product.find(params[:id])
@orders = @product.orders
respond_to do |format|
format.html
format.atom { render :layout => false }
format.xml { render :layout => false ,
:xml => @product.to_xml(:include => :orders) }
end
end
protected
def authorize
end
end
curl --silent http://localhost:3000/info/who_bought/3.atom
<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
<id>tag:localhost,2005:/info/who_bought/3</id>
<link type="text/html" rel="alternate" href="http://localhost:3000"/>
<link type="application/atom+xml" rel="self" href="http://localhost:3000/info/who_bought/3.atom"/>
<title>Who bought Pragmatic Version Control</title>
<updated>2012-06-29T19:12:46Z</updated>
<entry>
<id>tag:localhost,2005:Order/1</id>
<published>2012-06-29T19:12:46Z</published>
<updated>2012-06-29T19:12:46Z</updated>
<link type="text/html" rel="alternate" href="http://localhost:3000/orders/1"/>
<title>Order 1</title>
<summary type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
<p>Shipped to 123 Main St</p>
<table>
<tr>
<th>Product</th>
<th>Quantity</th>
<th>Total Price</th>
</tr>
<tr>
<td>Pragmatic Version Control</td>
<td>1</td>
<td>$28.50</td>
</tr>
<tr>
<th colspan="2">total</th>
<th>$28.50</th>
</tr>
</table>
<p>Paid by check</p>
</div>
</summary>
<author>
<name>Dave Thomas</name>
<email>customer@example.com</email>
</author>
</entry>
</feed>
edit app/controllers/info_controller.rb
class InfoController < ApplicationController
def who_bought
@product = Product.find(params[:id])
@orders = @product.orders
respond_to do |format|
format.html
format.atom { render :layout => false }
format.xml { render :layout => false ,
:xml => @product.to_xml(:include => :orders) }
format.json { render :layout => false ,
:json => @product.to_json(:include => :orders) }
end
end
protected
def authorize
end
end
curl --silent -H "Accept: application/json" http://localhost:3000/info/who_bought/3
{"product":{"price":"28.5","created_at":"2012-06-29T19:11:41Z","image_url":"/images/svn.jpg","title":"Pragmatic Version Control","updated_at":"2012-06-29T19:11:41Z","id":3,"orders":[{"name":"Dave Thomas","address":"123 Main St","created_at":"2012-06-29T19:12:46Z","updated_at":"2012-06-29T19:12:46Z","pay_type":"check","id":1,"email":"customer@example.com"}],"description":"<p>\n This book is a recipe-based approach to using Subversion that will \n get you up and running quickly---and correctly. All projects need\n version control: it's a foundational piece of any project's \n infrastructure. Yet half of all project teams in the U.S. don't use\n any version control at all. Many others don't use it well, and end \n up experiencing time-consuming problems.\n </p>"}}
mv app/controllers/info_controller.save app/controllers/info_controller.rb
rake doc:app
rm -r doc/app
option --inline-source is deprecated: source code is now always inlined
Generating Darkfish format into /home/rubys/git/awdwr/edition3/work-30/depot/doc/app...
Files: 23
Classes: 14 ( 8 undocumented)
Modules: 8 ( 8 undocumented)
Constants: 1 ( 0 undocumented)
Attributes: 4 ( 4 undocumented)
Methods: 57 ( 9 undocumented)
Total: 84 (29 undocumented)
65.48% documented
Elapsed: 1.5s
rake stats
+----------------------+-------+-------+---------+---------+-----+-------+
| Name | Lines | LOC | Classes | Methods | M/C | LOC/M |
+----------------------+-------+-------+---------+---------+-----+-------+
| Controllers | 503 | 337 | 8 | 42 | 5 | 6 |
| Helpers | 22 | 22 | 0 | 1 | 0 | 20 |
| Models | 231 | 130 | 6 | 19 | 3 | 4 |
| Libraries | 0 | 0 | 0 | 0 | 0 | 0 |
| Integration tests | 0 | 0 | 0 | 0 | 0 | 0 |
| Functional tests | 233 | 185 | 7 | 0 | 0 | 0 |
| Unit tests | 60 | 45 | 11 | 0 | 0 | 0 |
+----------------------+-------+-------+---------+---------+-----+-------+
| Total | 1049 | 719 | 32 | 62 | 1 | 9 |
+----------------------+-------+-------+---------+---------+-----+-------+
Code LOC: 489 Test LOC: 230 Code to Test Ratio: 1:0.5
13 Task I: Internationalization 11.4 Iteration F4: Adding a Sidebar, More Administration