The Depot Application

The Depot Application

13 Task I: Internationalization 11.4 Iteration F4: Adding a Sidebar, More Administration

12.1 Generating the XML Feed

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
/home/rubys/.rvm/gems/ruby-1.9.3-r28929/gems/bundler-1.0.0.rc.3/lib/bundler.rb:183: Use RbConfig instead of obsolete and deprecated Config.
      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 = 2010-08-08 16:21:46.301444
 updated_at = 2010-08-08 16:21:46.301444
      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 = 2010-08-08 16:21:46.307357
 updated_at = 2010-08-08 16:21:46.307357
      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 = 2010-08-08 16:21:46.310138
 updated_at = 2010-08-08 16:21:46.310138
      price = 27.75
sqlite3> select * from line_items
         id = 1
 product_id = 3
   order_id = 1
   quantity = 1
total_price = 28.5
 created_at = 2010-08-08 16:22:25.376032
 updated_at = 2010-08-08 16:22:25.376032
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?1281284541" media="all" rel="stylesheet" type="text/css" />
<!-- END:stylesheet -->
  <script src="/javascripts/prototype.js?1281284466" type="text/javascript"></script>
<script src="/javascripts/effects.js?1281284466" type="text/javascript"></script>
<script src="/javascripts/dragdrop.js?1281284466" type="text/javascript"></script>
<script src="/javascripts/controls.js?1281284466" type="text/javascript"></script>
<script src="/javascripts/rails.js?1281284466" type="text/javascript"></script>
<script src="/javascripts/application.js?1281284466" type="text/javascript"></script>
</head>
<!-- END:jit -->
<body id="store">
  <div id="banner">
    <img alt="Logo" src="/images/logo.png?1281284506" />
    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>
  <created-at type="datetime">2010-08-08T16:21:46Z</created-at>
  <description>&lt;p&gt;
         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.
      &lt;/p&gt;</description>
  <id type="integer">3</id>
  <image-url>/images/svn.jpg</image-url>
  <price type="decimal">28.5</price>
  <title>Pragmatic Version Control</title>
  <updated-at type="datetime">2010-08-08T16:21:46Z</updated-at>
  <orders type="array">
    <order>
      <address>123 Main St</address>
      <created-at type="datetime">2010-08-08T16:22:25Z</created-at>
      <email>customer@example.com</email>
      <id type="integer">1</id>
      <name>Dave Thomas</name>
      <pay-type>check</pay-type>
      <updated-at type="datetime">2010-08-08T16:22:25Z</updated-at>
    </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 rel="alternate" type="text/html" href="http://localhost:3000"/>
  <link rel="self" type="application/atom+xml" href="http://localhost:3000/info/who_bought/3.atom"/>
  <title>Who bought Pragmatic Version Control</title>
  <updated>2010-08-08T16:22:25Z</updated>
  <entry>
    <id>tag:localhost,2005:Order/1</id>
    <published>2010-08-08T16:22:25Z</published>
    <updated>2010-08-08T16:22:25Z</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>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":{"created_at":"2010-08-08T16:21:46Z","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>","id":3,"image_url":"/images/svn.jpg","price":"28.5","title":"Pragmatic Version Control","updated_at":"2010-08-08T16:21:46Z","orders":[{"address":"123 Main St","created_at":"2010-08-08T16:22:25Z","email":"customer@example.com","id":1,"name":"Dave Thomas","pay_type":"check","updated_at":"2010-08-08T16:22:25Z"}]}}
mv app/controllers/info_controller.save app/controllers/info_controller.rb
rake doc:app
/home/rubys/.rvm/gems/ruby-1.9.3-r28929/gems/bundler-1.0.0.rc.3/lib/bundler.rb:183: Use RbConfig instead of obsolete and deprecated Config.
rm -r doc/app
invalid options: --line-numbers, --inline-source
(invalid options are ignored)
(in /home/rubys/git/awdwr/work-193/depot)
Parsing sources...
  4% [ 1/23]   doc/README_FOR_APP
  8% [ 2/23]   app/helpers/application_helper.rb
 13% [ 3/23]   app/helpers/store_helper.rb
 17% [ 4/23]   app/helpers/info_helper.rb
 21% [ 5/23]   app/helpers/admin_helper.rb
 26% [ 6/23]   app/helpers/line_items_helper.rb
 30% [ 7/23]   app/helpers/orders_helper.rb
 34% [ 8/23]   app/helpers/users_helper.rb
 39% [ 9/23]   app/helpers/products_helper.rb
 43% [10/23]   app/controllers/users_controller.rb
 47% [11/23]   app/controllers/store_controller.rb
 52% [12/23]   app/controllers/line_items_controller.rb
 56% [13/23]   app/controllers/application_controller.rb
 60% [14/23]   app/controllers/info_controller.rb
 65% [15/23]   app/controllers/admin_controller.rb
 69% [16/23]   app/controllers/products_controller.rb
 73% [17/23]   app/controllers/orders_controller.rb
 78% [18/23]   app/models/cart.rb
 82% [19/23]   app/models/cart_item.rb
 86% [20/23]   app/models/user.rb
 91% [21/23]   app/models/product.rb
 95% [22/23]   app/models/line_item.rb
100% [23/23]   app/models/order.rb

    
Generating Darkfish...
 
 
Files:        23
Classes:      14 (    8 undocumented)
Constants:     1 (    0 undocumented)
Modules:       8 (    8 undocumented)
Methods:      62 (    9 undocumented)
 70.59% documented
 
Elapsed: 1.0s
rake stats
/home/rubys/.rvm/gems/ruby-1.9.3-r28929/gems/bundler-1.0.0.rc.3/lib/bundler.rb:183: Use RbConfig instead of obsolete and deprecated Config.
(in /home/rubys/git/awdwr/work-193/depot)
+----------------------+-------+-------+---------+---------+-----+-------+
| 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