本文将讨论RoR中提供的基础服务之一:动作视图。动作视图可以使你更快速地将数据展现给用户。在本文中将介绍一些动作视图的服务,并且将举一个例子来说明如何使用动作视图。
在MVC模式中的V,即视图(View),它的作用是将数据以用户所需要的形式展现出来,和传统的模式不同的是,视图在展现数据时可以省去许多不必要的 细节。也就是说,任何基于MVC模式的框架(framework)都应该提供更容易的方法提取和显示需要的数据。RoR就是这样的框架。它将动作视图作为 其核心组件之一。
在本文中,将主要讨论动作视图的基础服务。第一部分介绍了和动作视图相关的服务。在第二和第三部分讨论动作视图的一些基本功能,在最后一部分,将给出一个实例来说明如何使用动作视图。
动作视图的服务
视图的功能就是向用户展现数据。下面列举了动作视图中的主要服务:
·模板
·布局
·分页
当然,在动作视图中还在很多的服务,但上面的三个服务在动作视图中是最重要的。
模板
所谓模板,就是在一个文件中预定义了一些共用的资源,应用程序通过使用这些共用的资源,可以简化应用程序的开发过程,从而达到重用的目的。在动作视图中 的模板所包含的资源主要就是布局信息、一些数据所存放的路径等。在动作视图中的模板很多,如HTML格式的登录模板、以及Email模版等。
布局
从软件(包括Web和桌面程序)上来说,布局就是将GUI中的控件进行组织和安排,也就是说布局控制着GUI控件(如按钮、文本框等)如何被放置在界面上。例如,布局可通过垂直等间距方式将要排列的控件按垂直方向等间距进行排列。
分页
分页的作用就是将大量的数据分批地显示在页面上,可通过"上一页"和"下一页"进行页间的切换。分页有些象用打印机打一个大的文档,一张纸打不下,就将 数据分成多张纸来打。虽然将分页这种显示数据的方式应用到程序中可以解决大数据量显示的问题,但这同时又会带来另外一个问题,那就是如果对数据进行导航, 也就是翻页问题。
除了以上提到的服务外,在动作视图中还有其它的服务,如格式化助手等。但是上面所介绍的三个服务是动作视图中最重要的。在下一部分,我们将讨论如何使用这些服务。
模板和格式化助手
动作视图为我们提供了很多建立动态视图的服务。下面是动作视图提供的主要的服务:
·模版
·格式化助手
·分页
·布局
上面的4种服务,除了格式化助手外,其它三个服务都已经在前面介绍过了。
模板
就象以前讨论的一样,在模板中包含了一些代码、标记、简单文本或它们的组合。在其中的代码可以通过Controller中的访问信息提供动态的内容。代码通过执行环境访问信息。这个环境为代码提供了以下的信息:
1. Controller的实例变量,通过这些变量可以将数据从Controller传给模板。
2. 作为存取器的Controller对象。这些对象包括对象头、参数、请求、响应和会话。
3. 当前正在使用的Controller对象。模板代码可以从这个Controller对象中调用它的public方法。
在RoR中的模板是RHTML文件。RHTML文件有些类似于JSP文件,在RHTML文件中有静态的HTML,也有动态的内容。动态的内容可以由内嵌的代码生成技术产生,也可以用手工编写。如以下的RHTML文件显示了当前的日期和时间:
<h1>大家好!</h1> <p> <b> 当前日间: <%= Time.now %> </b> </p> |
和JSP类似,在RHTML中有两种写动态代码的方法,一种是将代码写到<%= … %>中,另外一种是将代码写在<% … %>中。在<%= … %>中的Ruby语句只是当作一个值返回,如果其中含有多条语句,则返回最后一条语句的值。而将代码放到<% … %>中,则按着正常的程序逻辑执行。虽然RHTML中可以执行Ruby语句,但最好不要将商业逻辑代码写在RHTML中。代码的执行原理可看下面的例子。
如果有以下代码:
<% 5.times do %> <5> <% end %> |
在执行RHTML时,将上述代码转换为Ruby语句:
5.times do puts "<5>" end |
格式化助手
视图的一个重要功能就是可以将从Controller传过来的数据进行格式化,以便用户更容易理解这些数据。RoR提供的格式化助手就是用来完成这个功能的。格式化助手主要可以格式化三类信息:数字、日期和文本。下面将讨论如何使用格式化助手对这些信息进行格式化。
数字和日期格式化
格式化助手可以进行多种的转换工作,如将本地时间转换成另外一种形式,将数字转换成货币类型、百分比或电话号,下面是一些转换的例子: <%= distance_of_time_in_words(Time.now, Time.local(2006, 11, 1)) %>
将得到4或其它的数字(根据你运行它的日期不同而不同)
<%= distance_of_time_in_words(Time.now, Time.now + 40, false) %> |
将得到1分钟(40表示秒)
<%= number_to_currency(99.99) %> |
将得到$99.99
<%= number_to_percentage(66.6666) %> |
将得到 66.667%
<%= number_to_percentage(66.66666, :precision => 1) %> |
将得到 66.7%
<%= number_to_phone(1125551212) %> |
将这个数字转换为 112-555-1212
格式化文本
同样,格式化助手也可以格式化文本。格式化操作包括截取字符串,加亮显示字符串中的子字符串,甚至可以将一个单词转换成复数。下面是一些字符串的例子:
替换字符串的子串
<%= excerpt(@str, "you", 8) %> |
如果@str中的字符串是 "I love …",那么就应该返回"I love you"
<%= highlight(@str, "love") %> |
如果@str中的字符串是"I love you."
那应该显示:
I <strong class="highlight">love</strong> you. |
在字符串转换中,最有意思转换可能就是将英文单词的单数形式转换成复数形式(你可以用这个功能查一下单词的复数形式是什么)。
<%= pluralize(2, "person") %> |
显示 2 people.
分页
在第一部分我介绍了分页的概念。在这部分我将讨论如何通过RoR使分页变得更容易。RoR通过控制层和视图层实现分页。在控制层,RoR的分页系统控制 从数据库中得到的记录。在视图层显示从控制层得到的数据,以及用于分页显示的导航条。下面的例子描述了将users表分页显示的过程:
控制层的实现:
在控制层,分页必须按如下代码实现:
def user_list @user_pages, @users = paginate(:users, :order_by => 'name') end |
以上代码通过paginate方法设置的分页器。这个方法有两个参数,第一个参数是要读取数据的表的名子,第二个参数是在取数据时要排序的字段。这个方 法返回两个对象,第一个对象@user_pages是分页器对象, 第二个对象 @users 是每一页的记录数。其中@users用来向视图提供要显示的数据。 而@user_pages负责从表中得到数据,然后将这些数据保存在@users中。
视图层的实现:
在视图层的RHTML文件中,@users中的数据将被展现给用户。pagination_links()方法可以实现导航的功能。以下是具体的实现代码:
<table> <tr><th>姓名</th></tr> <% for user in @users %> <tr><td><%= user.name %></td> <% end %> </table> <hr> <%= pagination_links(@user_pages) %> <hr> |
看看上面的代码是不是很简单!!
布局
在模板中可以通过布局提供子模板。这就意味着RoR可以通过布局进行嵌套操作。布局提供了一个典型网页的各种组成部分,如菜单、页脚等。下面是一个简单的关于布局的例子。
<html> <head> <title>Form: <%= controller.action_name %></title> <%= stylesheet_link_tag 'scaffold' %> </head> <body> <%= @content_for_layout %> </body> </html> |
上面的代码是一个标准的HTML布局。最值得关注的是变量@content_for_layout。这个变量中保存了从控制层传过来的数据。下面代码演示了如何从控制层传递数据到一个RHTML文件:
def method @msg ="测试!" end |
下面是method.rhtml 文件中的代码:
<h1><%= @msg %></h1> |
变量@content_for_layout 的内容如下:
<h1>测试!</h1> |
由布局生成的HTML代码如下:
<html> <head> <title>Form: method</title> <link href="/stylesheets/scaffold.css" media="screen" rel="Stylesheet" type="text/css"/> </head> <body> <h1>测试!</h1> </body> </html> |
上面的例子只是简单地演示了如何使用布局。在RoR提供的自动生成代码机制中的scaffold就是使用布局来生成的输出文件。在下一部分将给一个简单的例子来演示如何使用模板和格式化技术。
实例
在这个例子中显示了一些被格式化的时间、字符串和数字。
下面的代码是控制层的代码:
class SayController < ApplicationController def hello @time=Time.now end end |
下面是视图层(这个文件就是一个模板)的代码:
<html> <head> <title>你好!</title> </head> <body> <h1>现在报时:<%=@time%></h1> </body> </html> |
现在让我们使用格式化功能:
class SayController < ApplicationController def hello @time=Time.now @rule="This is a rule" @price=123 end end |
下面在视图中使用格式化助手进行格式化:
<html> <head> <title>你好!</title> </head> <body> <br>现在报时:<%=@time%> <br>时间间隔:<%= distance_of_time_in_words(@time, Time.local(2006, 10, 11)) %> <br>高亮度显示rule:<%= highlight(@rule, "rule") %> <br>将123转换成美元: <%= number_to_currency(@price) %> </body> </html> |