我们已经给卖家创建了管理products的页面,现在创建第二个控制器,为买家创建一个与卖家的交互控制器,称为store。
>ruby script/generate controller store index
D:\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.html.erb
D:\rails\depot>
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.html.erb
D:\rails\depot>
因为rails没有指定一个action来调用控制器的话,rails会自动调用index()方法。
我们重启server,进入http://localhost:3000/store,你会看到如下页面。

这个自动生成页面意味着一切还正常。我们先设计一个简单的页面,显示数据库中可以销售的货物。
先去修改store_controller.rb文件中的index方法。
app/controllers/store_controller.rb
class StoreController < ApplicationController
def index
@products = Product.find_products_for_sale
end
end
很显然这还远远不够。我们在product.rb文件中去定义find_products_for_sale方法。下面的代码就是该方法的实现,其中使用了rails提供的find方法, :all参数代表我们希望去除符合指定条件的所有记录,并且按名称对货物排序。
app/models/product.rb
class Product < ActiveRecord::base
def sef.find_products_for_sale
find(:all, :order => "title")
end
#validation stuff
end
find()方法会返回一个数组,其中的每个元素是一个Product对象,分别从数据库返回一条记录。find_products_for_sale方法直接把这个数组返回给控制器。我们在find_products_for_sale方法前面加上self,这样我们可以直接通过Product.find_products_for_sale来调用它。
现在我们去编辑视图模板。
app/views/store/index.html.erb
<h1>Your Pragmatic Catalog</h1>
<% for product in @products -%>
<div class="entry">
<%= image_tag(product.image_url) %>
<h3><%=h product.title %></h3>
<%= product.description %>
<span class="price"><%= product.price %></span>
</div>
<% end %>
按刷新按钮,我们就看到了下图类似的页面。这个页面的美观性不做评价,因为我们没有添加任何css样式表进去。

让我们为了更为美观的页面去添加一个页面布局。布局就是一个模板。我们可以将货物信息填充进去,可以把“购物车”,“结账”的页面也放进同样的布局。
如果在app\views\layouts目录中创建了一个与某控制器同名的模板文件,那么该控制器所渲染的视图在默认状态下会使用此布局模板。我们的控制器叫store,我们去创建一个叫store.html.erb的模板。
app/views/layouts/store.html.erb
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Pragprog Books Online Store</title>
<%= stylesheet_link_tag "depot", :media => "all" %>
</head>
<body id="store">
<div id="banner">
<%= image_tag("logo.png") %>
<%= @page_title || "Pragmatic Bookshelf" %>
</div>
<div id="columns">
<div id="side">
<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 />
</div>
<div id="main">
<%= yield :layout %>
</div>
</div>
</body>
</html>
这个模板的代码除了一般的html代码,还包涵了三个rails特有的东西。第6行中使用了一个Rails辅助方法,用于生成指向depot.css样式表的<link>标签。第11行我们将页面的开头设置为@page_title变量的值。在第21行,我们调用yield方法并传入:layout时,Rails会自动在这里插入页面的内容!也就是在真实生成的页面中,index.html.erb占据了页面的右下部分。

我们对表示价格的数字格式化一下。在index模板中将
<span class="price"><%= product.price %></span>
改成
Code
最后我们添加一个“add to cart”的按钮链接,使用button_to()方法。
<%= button_to "Add to Cart", :action => :add_to_cart %>
现在app/views/store/index.html.erb
<h1>Your Pragmatic Catalog</h1>
<% for product in @products -%>
<div class="entry">
<%= image_tag(product.image_url) %>
<h3><%=h product.title %></h3>
<%= product.description %>
<span class="price"><%= number_to_currency(product.price) %></span>
<%= button_to "Add to Cart", :action => :add_to_cart, :id => product %>
</div>
<% end %>
我们再在depot.css中添加上几行,避免“add to cart”按钮另起一行。
#store .entry form, #store .entry form div {
display: inline;
}
现在再看看我们的页面。


浙公网安备 33010602011771号