Depot App Who Bought Enhancements

I've completed the chapter on Internationalization successfully, but
found out just recently that the "Who Bought" function produces an
error page that looks very ugly when someone enters a product ID that
does not exist. My preference would be to design the app to have a
list of hyperlinks presented when you visit the URL, http://localhost:3000/info/
that describes the list of "Info Functions" (eg "Who Bought" for
starters). Then when it takes you there, http://localhost:3000/info/who_bought/
you would see a list of Book Titles as hyperlinks so that when you
click on a book title, it redirects you to the appropriate URL for
seeing a list of customers "who bought" that book. In this way I
could avoid the user's temptation to use "non-existent" product ID's
before it becomes a problem. But I have no idea how to go about
creating these features. I'm open to some ideas.

Arthur

To keep things simple for the moment, I created a file in /home/arthur/
RubySites/depot/app/views/info with a filename of index.html.erb and
put the following code into it:

<h3>Info Functions</h3>

<a href="http://localhost:3000/info/who_bought">Who Bought</a>

Of course when you click this hyperlink, the file who_bought.html.erb
responds with:

ActiveRecord::RecordNotFound in InfoController#who_bought

Couldn't find Product without an ID

So, my guess would be that I need to "test" for the condition where
the ID is missing and write some code in that file that loops through
the products table and creates hyperlinks such as:

<a href="http://localhost:3000/info/who_bought/1.html">Pragmatic
Project Automation</a>

for each book title in the database.

I have to think about the syntax for all of that...any ideas?

Arthur

I think I'm pretty close now. There are 3 files involved:

app/contollers/info_controller.rb which contains:

class InfoController < ApplicationController
  def who_bought
    if params[:id] == nil then
      @products = Product.all
      respond_to do |format|
        format.html
        format.xml { render :xml => @products }
      end
    else
      @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
  end
end

app/views/info/who_bought.html.erb which contains:

if @products != nil then
  <% for product in @products %>
    <a href="http://localhost:3000/info/who_bought/"+<%=h product.id %>
+".html"><%=h product.title %></a>
  <% end %>
else
  <h3>People Who Bought <%= @product.title %></h3>
  <ul>
    <% for order in @orders -%>
       <li>
         <%= mail_to order.email, order.name %>
       </li>
    <% end -%>
  </ul>
end

app/views/info/index.html.erb which contains:

<h3>Info Functions</h3>

<a href="http://localhost:3000/info/who_bought">Who Bought</a>

The problem is that when I visit http://localhost:3000/info/who_bought/

I get the following error screen:

NoMethodError in Info#who_bought

Showing app/views/info/who_bought.html.erb where line #6 raised:

You have a nil object when you didn't expect it!
The error occurred while evaluating nil.title

Extracted source (around line #6):

3: <a href="http://localhost:3000/info/who_bought/"+<%=h
product.id %>+".html"><%=h product.title %></a>
4: <% end %>
5: else
6: <h3>People Who Bought <%= @product.title %></h3>
7: <ul>
8: <% for order in @orders -%>
9: <li>

And I think I know why this is happening. I think that the if
statement test in who_bought.html.erb is always causing the execution
to fall into the else clause. My question is what test statement will
give me what I want?

Arthur