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