第十六章 改进控制器和视图
第2版的 R4RMusic 的控制器动作及相应模版总结
控制器 | 描述 | 动作方法名 | 主模板 |
Customer | 登录 注销 注册一个新帐号 给购物车添加一个版本 查看购物车 结帐(购买完毕) | login logout signup add_to_cart view_cart check_out | main/welcome.rhtml main/welcome.rhtml main/welcome.rhtml customer/view_cart.rhtml customer/view_cart.rhtml customer/check_out.rhtml |
Main | 欢迎访问者 显示给定时代的所有作品 | welcome show_period | main/welcome.rhtml main/show_period.rhtml |
Composer | 显示某作曲者作品的所有版本 | show | composer/show.rhtml |
Edition | 显示版本的详细出版信息 | show | edition/show.rhtml |
Instrument | 显示给定乐器的所有作品 | show | instrument/show.rhtml |
Work | 显示给定作品的所有版本 | show | work/show.rhtml |
R4RMusic 最终版下载:http://kerryas.googlecode.com/files/r4rmusic.rar
一、为视图模板定义辅助方法
1. 组织和访问定制的辅助方法
在 app/helper 目录下是对于每个控制器的辅助文件 controller_helper.rb,例如,composer_helper.rb 包含下面内容
module ComposerHelper
end
把方法定义到辅助文件中可以有助于减少重复代码,可以编写一个自动产生链接的辅助方法
module ComposerHelper
end
下面是如何在模版中使用这个新的 link_to_composer 方法的例子
<ul>
</ul>
使用其它辅助文件中的方法
方法一:在辅助方法的控制器中,将该方法声明为 helper,例如
class MainController < ApplicationController
end
方法二:把辅助文件放到通用的辅助文件 application_helper.rb 中,这样对于所有的控制器和模版来说这些方法都是可见的。
2. 为 R4RMusic 定制的辅助方法
方法 | 定义于 | 通过 helper 包含到这些控制器中 |
link_to_composer link_to_work link_to_edition link_to_edition_title link_to_instrument two_dec | composer_helper.rb work_helper.rb edition_helper.rb edition_helper.rb instrument_helper.rb application_helper.rb | customer, edition, main composer, customer, edition, instrument, main customer, work composer, instrument main 可被所有控制器访问 |
下面是前五个辅助方法的定义:
def link_to_composer(composer)
end
def link_to_edition(edition)
end
def link_to_edition_title(edition)
end
def link_to_work(work)
end
def link_to_instrument(instrument)
end
第六个辅助方法将一个浮点数转换为一个包含两个十进制小数的字符串
module ApplicationHelper
end
二、编码和部署部分视图模板
1. 剖析主模板
首先查看 composer/show.html.erb 模板文件
<% @page_title = "Editions of works by #{@composer.whole_name}" %>
其中 render 方法检查部分模版名字,在它前面添加一下划线,在它后面添加一个 .html.erb 后缀,下面是 composer/_editions.html.erb
<ul>
</ul>
2. 在欢迎视图模板中使用部分模版
(1)生成作曲者链接清单
创建作曲者链接清单 composer/_list.html.erb
<ul>
将下面这一行放到主模板 main/welcome.html.erb 中
<%= render :partial => "composer/list" %>
(2)生成乐器链接清单
部分模版 instrument/_list.html.erb
<ul>
</ul>
创建 instrument 控制器:
F:\ruby_project\R4Rmusic>ruby script/generate controller instrument show
完成 instrument_controller.rb 文件:
class InstrumentController < ApplicationController
(3)生成音乐时代的链接清单
产生音乐时代的链接清单 main/_period_list.html.erb
<ul>
</ul>
我们也需要为在 welcome 模板中加入部分模板
<%= render :partial => "period_list" %>
(4) 完整的欢迎模板(views/main/welcome.html.erb)
<% if @c %>
三、更新主控制器
Welcome 动作新面孔(main_controller.rb):
class MainController < ApplicationController
end
四、加入顾客注册的登录动作
1. 登录和注册部分模板
(1)注册模板 customer/_signup.html.erb
<% form_tag :controller => "customer",
<% end %>
(2)登录模板 customer/_login.html.erb
<% form_tag :controller => "customer",
<% end %>
2. 登录和保存会话状态
def login
end
3. 用 before_filter 看守动作(ApplicationController.rb)
class ApplicationController < ActionController::Base
end
如果 session 中已经保存了用户的 ID ,那么数据库中可以查找出该对象则 @c 不为空,否则 @c 为空那么,主界面中显示提示用户登录:
<% if @c %>
<% else %>
<% end %>
我们还希望过滤器能在顾客没有登录的情况下拦截请求动作(CustomerController.rb)
before_filter :authorize, :except => ["signup","login"]
def authorize
end
其中 report_error 是一个自制的、通过错误报告方法,被定义在 application.rb 中
class ApplicationController < ActionController::Base
end
该方法把传入的消息赋值给 @message 实例变量,呈现在 app/views/main/error.html.erb
4. 实现注册功能(CustomerController.rb)
def signup
end
使用 before_filter 技术,进行表单数据的验证,创建一个 new_customer 的过滤器,仅让它在 signup 动作之前作为过滤器执行
before_filter :new_customer, :only
def new_customer
end
5. 编写顾客注销脚本(在 app/view/layout/base.html.erb 中加入注销按钮,加在 body 中)
<table>
</table>
五、处理顾客订单
首先为 app/controllers/customer_controller.rb 添加一个动作
def view_cart
end
然后实现 view_cart.html.erb 视图
<% @page_title = "Shopping cart for #{@c.nick}" %>
<%= render :partial => "cart" %>
以下是购物车视图的 customer/_cart.html.erb 部分模板
<table border="1">
<% @c.editions_on_order.each do |edition| %>
<% count = @c.copies_of(edition) %>
<% end %>
</table>
<p><%= link_to("Complete purchases",
2. 查看和购买一个版本
查看版本的主模板,edition/show.html.erb
<% @page_title = @edition.nice_title %>
<h2 class="info"><%= @page_title %></h2>
<%= render :partial => "details" %>
查看版本的部分模板,edition/_details.html.erb 部分模板
<ul>
<% if @c %>
<% end %>
</ul>
<h3>Contents:</h3>
<ul>
<% @edition.works.each do |work| %>
<% end %>
</ul>
3. 定义 add_to_cart 动作(CustomerController.rb)
def add_to_cart
end
4. 完成订单
在 CustomerController.rb 中定义
def check_out
end
再定义 app\views\customer\check_out.html.erb 作为结算完成视图,内容如下
<% @page_title = "Orders complete" %>
<h2>Thanks for your order, <%= @c.first_name %>!</h2>
六、通过动态代码使页面人性化
1. 从排名到喜好
在 app/models/customer.rb 中定义
def rank(list)
end
def composer_rankings
end
def instrument_rankings
end
def favorites(thing,options)
end
其中 favorites 方法根据 thing 参数动态选择用户喜好,给定的 count 选择数组相应的条目。如果该值比排名方法返回的数组 size 要大,那么用 nil 进行填充,最后 compact 将删除这些 nil。
2. 实际使用中的 favorites 特性
最后让我们来实现 main/_favorites.html.erb 部分模板
<h2 class="info">Your favorites</h2>
<% fav_composers = @c.favorites :composer,
<% fav_instruments = @c.favorites :instrument,
<ul>
<% fav_composers.each do |composer| %>
<% end %>
<% fav_instruments.each do |instrument| %>
<% end %>
</ul>