Agile Web Development with Rails, Edition 4

12.3 Iteration G3: Downloading an eBook 12.1 Iteration G1: Capturing an Order

12.2 Iteration G2: Atom Feeds

Missing <summary type="xhtml">.
<0> expected to be
>=
<1>.

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

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 < ApplicationRecord
  has_many :line_items
  has_many :orders, through: :line_items
  #...
end

Add to the routes

edit config/routes.rb

Fetch the Atom feed

curl --max-time 15 --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>2016-01-27T20:55:04Z</updated>
</feed>

Look at the headers

curl --max-time 15 --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
Content-Type: application/atom+xml; charset=utf-8
ETag: W/"ab1b46324fb9a7460925fbbd64099e65"
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: be957d8e-449b-47ed-9792-5e9ea4d38b33
X-Runtime: 0.006043
Transfer-Encoding: chunked
 
curl --max-time 15 --silent --dump - --output /dev/null --user dave:secret http://localhost:3000/products/2/who_bought.atom -H 'If-None-Match: W/"ab1b46324fb9a7460925fbbd64099e65"'
HTTP/1.1 304 Not Modified
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
ETag: W/"ab1b46324fb9a7460925fbbd64099e65"
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: f7f64022-5526-45b9-86d8-551d655d5fb3
X-Runtime: 0.005833
 
curl --max-time 15 --silent --dump - --output /dev/null --user dave:secret http://localhost:3000/products/2/who_bought.atom -H 'If-Modified-Since: '
HTTP/1.1 200 OK
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Content-Type: application/atom+xml; charset=utf-8
ETag: W/"ab1b46324fb9a7460925fbbd64099e65"
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: f59b1e0c-57a2-40db-b0a7-8d910ba1f856
X-Runtime: 0.014730
Transfer-Encoding: chunked
 

12.3 Iteration G3: Downloading an eBook 12.1 Iteration G1: Capturing an Order