Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Agile Web Development With Rails, 1st Edition (2005).pdf
Скачиваний:
28
Добавлен:
17.08.2013
Размер:
7.99 Mб
Скачать

 

 

ITERATION A4: PRETTIER LISTINGS

63

 

So, in a couple of minutes we’ve added validations that check

 

 

• The field’s title, description, and image URL are not empty.

 

 

• The price is a valid number greater than zero.

 

 

• The title is unique among all products.

 

 

• The image URL looks reasonable.

 

 

This is the full listing of the updated Product model.

 

File 65

class Product < ActiveRecord::Base

 

 

validates_presence_of :title, :description, :image_url

 

 

validates_numericality_of :price

 

 

validates_uniqueness_of :title

 

 

validates_format_of :image_url,

 

 

:with

=> %r{^http:.+\.(gif|jpg|png)$}i,

 

 

:message => "must be a URL for a GIF, JPG, or PNG image"

 

 

protected

 

 

 

def validate

 

 

 

errors.add(:price, "should be positive") unless price.nil? || price > 0.0

 

 

end

 

 

 

end

 

 

 

Nearing the end of this cycle, we ask our customer to play with the appli-

 

 

cation, and she’s a lot happier. It took only a few minutes, but the simple

 

 

act of adding validation has made the product maintenance pages feel a

 

 

lot more solid.

 

 

 

6.4 Iteration A4: Prettier Listings

 

Our customer has one last request (customers always seem to have one

 

last request). The listing of all the products is ugly. Can we “pretty it up”

 

a bit? And, while we’re in there, can we also display the product image

 

along with the image URL?

 

We’re faced with a dilemma here. As developers, we’re trained to respond

 

to these kinds of request with a sharp intake of breath, a knowing shake

 

of the head, and a murmured “you want what?” At the same time, we also

 

like to show off a bit. In the end, the fact that it’s fun to make these kinds

 

of changes using Rails wins out, and we fire up our trusty editor.

 

The Rails view in the file app/views/admin/list.rhtml produces the current

 

list of products. The source code, which was produced by the scaffold

 

generator, looks something like the following.

File 66

<h1>Listing products</h1>

 

<table>

 

<tr>

 

<% for column in Product.content_columns %>

 

<th><%= column.human_name %></th>

Prepared exclusively for Rida Al Barazi

Report erratum

ITERATION A4: PRETTIER LISTINGS

64

<% end %>

</tr>

<% for product in @products %>

<tr>

<% for column in Product.content_columns %> <td><%=h product.send(column.name) %></td>

<% end %>

<td><%= link_to 'Show', :action => 'show', :id => product %></td> <td><%= link_to 'Edit', :action => 'edit', :id => product %></td> <td><%= link_to 'Destroy', {:action => 'destroy', :id => product},

:confirm => "Are you sure?" %></td>

</tr> <% end %>

</table>

<%= if @product_pages.current.previous

link_to "Previous page", { :page => @product_pages.current.previous } end %>

<%= if @product_pages.current.next

link_to "Next page", { :page => @product_pages.current.next } end %>

<br />

<%= link_to 'New product', :action => 'new' %>

The view uses ERb to iterate over the columns in the Product model. It creates a table row for each product in the @products array. (This array is set up by the list action method in the controller.) The row contains an entry for each column in the result set.

The dynamic nature of this code is neat, as it means that the display will automatically update to accommodate new columns. However, it also makes the display somewhat generic. So, let’s take this code and modify it to produce nicer-looking output.

ERb

page 31

File 67

<h1>Product Listing</h1>

 

<table cellpadding="5" cellspacing="0">

 

<%

 

odd_or_even = 0

 

for product in @products

 

odd_or_even = 1 - odd_or_even

 

%>

 

<tr valign="top" class="ListLine<%= odd_or_even %>">

 

<td>

 

<img width="60" height="70" src="<%= product.image_url %>"/>

 

</td>

 

<td width="60%">

 

<span class="ListTitle"><%= h(product.title) %></span><br />

 

<%= h(truncate(product.description, 80)) %>

 

</td>

 

<td align="right">

 

<%= product.date_available.strftime("%y-%m-%d") %><br/>

 

<strong>$<%= sprintf("%0.2f", product.price) %></strong>

 

</td>

 

<td class="ListActions">

 

<%= link_to 'Show', :action => 'show', :id => product %><br/>

 

<%= link_to 'Edit', :action => 'edit', :id => product %><br/>

Prepared exclusively for Rida Al Barazi

Report erratum

 

ITERATION A4: PRETTIER LISTINGS

65

 

<%= link_to 'Destroy', { :action => 'destroy', :id => product },

 

 

:confirm => "Are you sure?" %>

 

 

</td>

 

 

</tr>

 

 

<% end %>

 

 

</table>

 

 

<%= if @product_pages.current.previous

 

 

link_to("Previous page", { :page => @product_pages.current.previous })

 

 

end

 

 

%>

 

 

<%= if @product_pages.current.next

 

 

link_to("Next page", { :page => @product_pages.current.next })

 

 

end

 

 

%>

 

 

<br />

 

 

<%= link_to 'New product', :action => 'new' %>

 

 

Notice how we used the odd_or_even variable to toggle the name of the CSS

 

 

class applied to alternating rows of the table. This will result in alternating

 

 

pastel-shaded lines for each product. (If you’re reading this on paper, you’ll

 

 

have to take our word for it about the pastels.) We also used Ruby’s sprintf( )

 

 

method to convert the floating-point price to a nicely formatted string.

 

 

All scaffold-generated applications use the stylesheet scaffold.css in the

 

 

directory public/stylesheets. We added our own styles to this file.

 

File 68

.ListTitle {

 

color: #244; font-weight: bold; font-size: larger;

}

.ListActions {

font-size: x-small; text-align: right; padding-left: 1em;

}

.ListLine0 {

background: #e0f8f8;

}

.ListLine1 {

background: #f8b0f8;

}

Put some images in the public/images directory and enter some product descriptions, and the resulting product listing might look something like Figure 6.7, on the next page.

A Rails scaffold provides real source code, files that we can modify and immediately see results. This approach gives us the flexibility we need to develop in an agile way. We can customize a particular source file and leave the rest alone—changes are both possible and localized.

Prepared exclusively for Rida Al Barazi

Report erratum

ITERATION A4: PRETTIER LISTINGS

66

Figure 6.7: Tidied-up Product Listing

So, we proudly show our customer her new product listing, and she’s pleased. End of task. Time for lunch.

What We Just Did

In this chapter we laid the groundwork for our store application.

We created three databases (development, test, and production) and configured our Rails application to access them.

We created the products table and used the scaffold generator to write an application to maintain it.

We augmented that generated code with validation.

We rewrote the generic view code with something prettier.

One thing that we didn’t do was discuss the pagination of the product listing. The scaffold generator automatically made use of Rails’ built-in pagination helper. This breaks the lists of products into pages of 10 entries each and automatically handles navigation between pages. We discuss this in more depth starting on page 340.

Prepared exclusively for Rida Al Barazi

Report erratum