第1章 任务B:分类显示
1.1 迭代B1:创建分类列表
现在我们来为买主来创建控制器,名称为Store。
E:/work/rails/depot>
ruby script/generate controller Store index
exists app/controllers/
exists app/helpers/
create app/views/store
exists test/functional/
create app/controllers/store_controller.rb
create test/functional/store_controller_test.rb
create app/helpers/store_helper.rb
create app/views/store/index.rhtml
|
在前一章里,我们用generate工具来为products表创建了脚手架。这一次,我们用它一新建一个控制器(名为StoreController),其中包含一个名为index()的action方法。
我们先来设计一个简单的列表页面,显示数据库中所有可销售的货品。可销售的货品的定义是,如果一个货品的“可用日期”正好是今天或者在今天之前,那么就应该将它显示出来。
我们的方案是修改store_controller.rb文件中的index()方法。
def index
@products = Product.salable_items
end
|
在这里,Product.salable_items是调用product.rb中的salable_items()方法,所以我们现在需要在product.rb中加入此方法。
def self.salable_items
find(:all,
:conditions => "date_available <= now()",
:order => "date_available desc")
end
|
在这里使用了Rails提供的find()方法,:all参数代表我们希望取出指定条件的所有记录。在我们这里,选取记录的条件是“可用日期不是在当前日期之后”,用MySQL提供的now()函数可以取得当前的日期和时间。
此外我们还要将最新的货品列在最前在,也就是将data_available字段倒序。
find()方法返回一个数组,其中每一个元素就是一个Product对象,分别代表从数据库返回的一条记录。salable_items()方法直接将这个数组返回给控制器。
那么好了,我们现在要编写视图模板。我们修改app/views/store/index.rhtml文件。在这里要注意的是,视图的路径名称是根据控制器的名称(store)和action的名称(index)来确定的,.rhtml部分则表示该文件是一个ERb模板。
<table cellpadding="5" cellspacing="0">
<% for product in @products %>
<tr valign="top">
<td>
<img src="<%= product.image_url %>" />
</td>
<td width="450">
<h3><%= h product.title %></h3>
<small>
<%= product.description %>
</samll>
<br/>
<strong>
$<%= sprintf("%0.2f",product.price) %>
</strong>
<%= link_to 'add to Cart' ,
:action => 'add_to_cart',
:id => product %>
<br/>
</td>
</tr>
<tr><td colspan="2"><hr/></td></tr>
<% end %>
</table>
|
访问一下
http://127.0.0.1:3000/store/看看效果吧。
1.2 迭代B2:添加页面装饰
现在我们来为我们的应用添加页面布局。
在Rails中,我们可以定义布局。所谓布局(layout)实际上就是一个模板,我们可以将内容填充到其中。
在Rails中,定义和使用布局的方式有好多种,我们现在使用一个最简单的一种。
我们在app/views/layouts目录中创建了一个与某个控制器同名的模板文件,那么该控制器所渲染的视图缺省下会使用此布局模板。
我们的控制器名叫store,所以我们的布局模板的名字就应该是store.rhtml。
<html>
<head>
<title>Pragprog Books Online Store</title>
<%= stylesheet_link_tag "depot", :media => "all" %>
</head>
<body>
<div id="banner">
<img src="/images/logo.png" />
<%= @page_title || "Pragmatic Bookshelf" %>
</div>
<div id="columns">
<div id="side">
<a href="#">Home</a><br/>
<a href="#">Questions</a><br/>
<a href="#">News</a><br/>
<a href="#">Contact</a><br/>
</div>
<div id="main">
<%= @content_for_layout %>
</div>
</div>
</body>
</html>
|
在这个布局模板中,包含了三样Rails特有的东西。
n
<%= stylesheet_link_tag "depot", :media => "all" %>
这是一个Rails辅助的方法,用于生成指向depot.css样式表的<link>标签。
n
@page_title
将页面抬头设置为@page_title变量的值。
n
<%= @content_for_layout %>
Rails会自动将@content_for_layou变量的值设置为页面的内容,也就是真实视图所生成的内容,在我们这里就是index.rhtml生成的分类列表页面。
我们现在还需要把app/views目录中的index.rhtml视图也整理一下:
<% for product in @products %>
<div class="catalogentry">
<img src="<%= product.image_url %>" />
<h3><%= h(product.title) %></h3>
<%= product.description %>
<span class="catalogprice">
<%= sprintf("$0.2f",product.price) %>
</span>
<%= link_to 'Add to Cart'
{:action => 'add_to_cart', :id => product},
:class => 'addtocart' %>
<br />
</div>
<div class="separator"> </div>
<% end %>
<%= link_to "Show my cart", :action => "display_cart" %>
|
我们已经改为使用<div>标签,并加上了css类名,以便对页面进行布局。为了给“Add to Cart”链接加上一人css类,我们必须在link_to()方法中使用可选的第三方参数,这样就可以为生的成的html标签指定属性。
css可参见“附录C 源代码àCSS文件à depot_final/public/stylesheets/depot.css”