12.4 Playtime 12.1 Iteration G1: Capturing an Order
Demonstrate various respond_to/format options, as well as "through" relations and basic authentication.
Define a "who_bought" member action
edit app/controllers/products_controller.rb
def who_bought
@product = Product.find(params[:id])
@latest_order = @product.orders.order(:updated_at).last
if stale?(@latest_order)
respond_to do |format|
format.atom
end
end
end
Define an Atom view (using the Atom builder)
edit app/views/products/who_bought.atom.builder
atom_feed do |feed|
feed.title "Who bought #{@product.title}"
feed.updated @latest_order.try(:updated_at)
@product.orders.each do |order|
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
order.line_items.each do |item|
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|
author.name order.name
author.email order.email
end
end
end
end
Add "orders" to the Product class
edit app/models/product.rb
class Product < ActiveRecord::Base
has_many :line_items
has_many :orders, through: :line_items
#...
end
Add to the routes
edit config/routes.rb
Depot::Application.routes.draw do
resources :orders
resources :line_items
resources :carts
get "store/index"
resources :products do
get :who_bought, on: :member
end
# The priority is based upon order of creation:
# first created -> highest priority.
# See how all your routes lay out with "rake routes".
# You can have the root of your site routed with "root"
root 'store#index', as: 'store'
# ...
end
Fetch the Atom feed
curl --silent --user dave:secret http://localhost:3000/products/2/who_bought.atom
<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
<id>tag:localhost,2005:/products/2/who_bought</id>
<link rel="alternate" type="text/html" href="http://localhost:3000"/>
<link rel="self" type="application/atom+xml" href="http://localhost:3000/products/2/who_bought.atom"/>
<title>Who bought CoffeeScript</title>
<updated>2013-04-28T13:16:58Z</updated>
<entry>
<id>tag:localhost,2005:Order/1</id>
<published>2013-04-28T13:16:58Z</published>
<updated>2013-04-28T13:16:58Z</updated>
<link rel="alternate" type="text/html" 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>CoffeeScript</td>
<td>1</td>
<td>$36.00</td>
</tr>
<tr>
<th colspan="2">total</th>
<th>$36.00</th>
</tr>
</table>
<p>Paid by Check</p>
</div>
</summary>
<author>
<name>Dave Thomas</name>
<email>customer@example.com</email>
</author>
</entry>
</feed>
Look at the headers
curl --silent --dump - --output /dev/null --user dave:secret http://localhost:3000/products/2/who_bought.atom
HTTP/1.1 200 OK
X-Frame-Options: SAMEORIGIN
X-Xss-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Ua-Compatible: chrome=1
X-Xhr-Current-Location: /products/2/who_bought.atom
Etag: "a67c464eed29834543e772383a094916"
Last-Modified: Sun, 28 Apr 2013 13:16:58 GMT
Content-Type: application/atom+xml; charset=utf-8
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: f85c8426-623b-427a-8b75-4d0c9e835c72
X-Runtime: 0.026521
Server: WEBrick/1.3.1 (Ruby/1.9.3/2013-02-22)
Date: Sun, 28 Apr 2013 13:16:59 GMT
Content-Length: 1324
Connection: Keep-Alive
Set-Cookie: request_method=GET; path=/
curl --silent --dump - --output /dev/null --user dave:secret http://localhost:3000/products/2/who_bought.atom -H 'If-None-Match: "a67c464eed29834543e772383a094916"'
HTTP/1.1 304 Not Modified
X-Frame-Options: SAMEORIGIN
X-Xss-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Ua-Compatible: chrome=1
X-Xhr-Current-Location: /products/2/who_bought.atom
Etag: "a67c464eed29834543e772383a094916"
Last-Modified: Sun, 28 Apr 2013 13:16:58 GMT
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: 09536548-9bec-4083-919d-a5c22acfa882
X-Runtime: 0.011578
Server: WEBrick/1.3.1 (Ruby/1.9.3/2013-02-22)
Date: Sun, 28 Apr 2013 13:16:59 GMT
Connection: close
Set-Cookie: request_method=GET; path=/
curl --silent --dump - --output /dev/null --user dave:secret http://localhost:3000/products/2/who_bought.atom -H 'If-Modified-Since: Sun, 28 Apr 2013 13:16:58 GMT'
HTTP/1.1 304 Not Modified
X-Frame-Options: SAMEORIGIN
X-Xss-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Ua-Compatible: chrome=1
X-Xhr-Current-Location: /products/2/who_bought.atom
Etag: "a67c464eed29834543e772383a094916"
Last-Modified: Sun, 28 Apr 2013 13:16:58 GMT
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: f5912acd-ad0e-47c6-ba0c-a3be6d78c42e
X-Runtime: 0.011768
Server: WEBrick/1.3.1 (Ruby/1.9.3/2013-02-22)
Date: Sun, 28 Apr 2013 13:16:59 GMT
Connection: close
Set-Cookie: request_method=GET; path=/