实例应用
我们以《RapidWeb Development mit Ruby on Rails》中的一个例子“项目管理应用”来描述Rails的REST方面的特性。
首先创建一个rails的应用:(原书中的rails为1.2)
> rails ontrack
创建 开发 和 测试 的数据库。
> mysql -u rails -p
Enter password: *****
mysql> create database ontrack_development;
mysql> create database ontrack_test;
mysql> quit
基于REST的rails 应用可以使用新的脚手架(scaffold)命令 scaffold_resource 来方便的创建。可以传递给生成器这样一些参数:在本例中,就是资源的名字 “project”, 和 这个model 的字段名字以及类型。字段的类型是必须的,因为我们要使用migration,以及在视图中显示这些字段。
> cd ontrack
> ruby script/generate scaffold_resource project name:string desc:text
生成器不仅生成了 model, controller, view, 还生成了完整的migration脚本,以及在 routes.rb 里生成了一个映射:map.resources :projects ,对于新生成controller来说,这是用于REST方面的最后一个映射项目。
创建表:
> rake db:migrate
如果我们来看看刚才生成的ProjectController,会发现其实并没有什么新鲜的东西,无非也就是这么一些操作:创建(create),读取 (retrieve),更新(update),删除(delete)这些操作。需要强调注意:这些操作都是针对Project这个资源的。 Controller 和 Action 看起来都很普通,但是仔细看一下,每个Action 都会有一些注释,这些注释表明了 url 和 http 所使用的动作。这些注释所体现的,就是 REST风格的 URL。接下来的章节,我们会仔细分析一下这些URL的内容。
REST 风格的 URL
REST风格的URL,并不像以往的Rails 应用一样,是由 controller/action/model id 所组成的,例如 /projects/show/1 。相反,REST风格的URL仅仅由 controller 和资源的id 所组成,例如/projects/1。
注意:我们一直再强调“资源”这个词。URL中没有了 action,我们也就看不到该对资源进行什么操作了。
“/projects/1”这个URL到底应该是显示一个资源,还是应该删除一个资源?答案来自我们之前提到的 http 协议的4个动作。
下面的列表可以展示 http 协议的4个动作是如何和REST风格的URL所关联的,并且什么样的组合,对应什么样的action:
有一点需要注意,之前我们也提到过,浏览器只能理解 POST 和 Get 两个动作,所以,当输入 http://localhost:3000/projects/1 的时候,会调用 show这个Action.所以,Rails 提供了一个辅助的方案来声称一个用于删除一个资源的链接:Delete 这个动作被放在一个隐藏的提交字段里(hidden field)提交给服务器;在创建新的资源的时候,也是适用相同的方法。这些内容都会在以下的章节里介绍。
在Action 中使用 respond_to
我们已经知道,我们可以通过一个 指定资源id的URL 和http协议的动作的组合,来调用一个 action。这使得一个URL看起来非常简洁:一个URL就指定了哪个资源要被操作,而不像以往那样去指定一个Action。
那么到底有什么样的需求,会让我们去使用这种风格的URL呢?一个 REST的action可以应付不同的客户端所需要的不同的信息格式。对于一个WEB迎来说,典型的客户端当然就是浏览器了,但是别忘了,对于一个web service 来说,它需要的则是 xml 格式的信息;对于一个RSS阅读器来说,它需要的则是 RSS格式的信息。对于客户端的请求,我们已经使用 scaffold 生成器生成了 CRUD 4个方法来处理。下面的代码片断展示了 “show” 这个 action 中 respond_to 的使用方法:
Listing 1.2: ontrack/app/controllers/projects controller.rb
# GET /projects/1
# GET /projects/1.xml
def show
@project = Project.find(params[:id])
respond_to do |format|
format.html # show.rhtml
format.xml { render :xml => @project.to_xml }
end
end
respond_to 方法是用了代码块(block)技术,在这个例子中,代码块(block)部分处理了2种格式的信息:html 和 xml。针对客户端不同的请求,会执行代码块(block)中不同的部分。例如如果客户端请求的是html 信息,那么会执行“format.html”,如果客户端请求的是xml 信息,那么会执行“format.xml”部分。
如果 format.html 代码块里是空的,那么默认就显示 show.rhtml。
控制 respond_to 可以通过2种方式:一是在 http-header 里面;二是在URL后面追加一些东西,也就是改变URL的样式。
改变URL的样式
第二种控制 action 返回不同格式的信息的方法,就是改变URL的样式。假设我们没有删除 id=1 这个资源project,那么我们通过以下这个方式来在浏览器里显示这个资源:http://localhost:3000/projects/1.xml
这里MAC的用户要注意,这种情况下 firefox 表现的不错,但是Safari就差些,因为Safari 会忽略xml 格式的信息。甚至 firefox 会把xml 显示的非常漂亮!到这里,我们已经知道一个controller 和 URL是如何工作的,在接下来的2个章节里,我们会学习如何在 controller 和 view 里使用和构造这种REST风格的URL。
好了,今天我们就介绍到这里,到现在为止都还是理论上的东西,下节将开始说view、controller中的rest风格。