- 浏览: 335191 次
- 性别:
- 来自: 北京
文章分类
最新评论
LetRails的一系列介绍:
- REST on Rails指南5: respond_to
- REST on Rails指南4:路由
- REST on Rails指南3: RESTful Design
- REST on Rails指南2:无穷尽的API
http://www.letrails.cn/archives/6/
LetRails 写道
PART I
在理解REST on Rails之前,有必要先思考一下这个问题:浏览器是如何工作的?在开始使用Rails构建一个网站之前,我对这个问题是这么认为的:
首先我会在地址栏输入一个URL,或者点击一个链接
然后浏览器会发送一个HTTP请求,并获取响应中的HTML代码
最后我会看到经过浏览器渲染的页面
就这么多,我甚至不知道Form是如何工作的,我觉得它跟点击链接没什么不同。
但在现实世界里,HTTP协议有很严格的指令用于定义浏览器应该如何向服务器发送请求,HTTP同HTML完全是两码事,HTML只不过是一种用于表现页 面内容的标记语言(Markup Language),而HTTP协议则允许浏览器从服务器获取各种类型的数据,HTML只是其中之一。事实上,HTTP协议定义了8中不同类型的请求,尽 管如此,我们最熟悉的可能还是下面两种:
GET,通过GET请求可以获取Web上的资源,每一个资源都由URL来唯一标识。
POST,通过发送一组数据到特定的URL来创建一个新资源。
PART II
你可能对我使用“资源”(Resource)这个词感到迷惑不解,事实上我第一次看到这个词时也跟你一样迷惑,但这正是REST的精髓所在,在REST的世界里,整个Web被看作一组资源的集合,而不是一张张的网页,这是什么意思呢?
昨天,我上当当买了几本书,又去维基百科查了几个词条,然后上新浪看了几条新闻,最后又在NBA网站上看了下骑士对马刺的比赛前瞻。
如果你想要理解REST,那么你就要转变你的思维,不要再认为以上这些东西都是一张张的网页,让我们以维基百科为例,我查阅的REST词条事实上并不是一张网页,它是一个资源,我们使用http://zh.wikipedia.org/wiki/REST访问这个资源,并取得了它的HTML表示,之所以是HTML,是因为浏览器只只是这种方式。
我承认这有些费解,http://zh.wikipedia.org/wiki/REST怎 么可能不是网页呢?事实上,确实不是,它是一个使用URL进行标识的资源,当我使用浏览器来访问它时,我得到了它的HTML表示,但维基百科可能还提供其 他形式的表示,比如一个PDF,一张JPG图片或者别的什么东西,而我之所以得到一个HTML,是因为我的Firefox发送了一个GET请求,并明确的 告诉了服务器,给我一个HTML表示。
再举个更浅显些的例子,比如我向南方航空定了张机票,他们可以通过HTML在浏览器中跟我确认,也可以发短信给我,或者发一封Mail,当然也可以选择最稳妥的方式,打个电话告诉我。事实上就是一种资源,多种表示。
希望经过这番唠叨,你能够理解我所说的,我的机票订单不止是个网页,它是一个资源,当然我可以选择通过浏览器以HTML的方式来查看它。
PART III
一旦你接受了Web就是个巨大的资源集合,这些资源可以使用任意多的方式来表示,而HTML只是其中一种时,你离真正掌握REST已经不远了,但在结束今 天的课程前,我还要在絮叨下:事实上,资源并不总是单个的东西,比如维基百科上介绍REST的文章,一张机票订单或者一堆NBA比赛数据,它也可以是一组 资源的集合,比如中国传统节日列表,你最好的朋友等等,它们都是资源。
现在,你应该已经理解了什么是资源,在下一节,我们将讲解如何通过HTTP来创建(Creation),读取(Reading),更新(Updating)和销毁(Destruction)一个资源。
LetRails 写道
在理解REST on Rails之前,有必要先思考一下这个问题:浏览器是如何工作的?在开始使用Rails构建一个网站之前,我对这个问题是这么认为的:
首先我会在地址栏输入一个URL,或者点击一个链接
然后浏览器会发送一个HTTP请求,并获取响应中的HTML代码
最后我会看到经过浏览器渲染的页面
就这么多,我甚至不知道Form是如何工作的,我觉得它跟点击链接没什么不同。
但在现实世界里,HTTP协议有很严格的指令用于定义浏览器应该如何向服务器发送请求,HTTP同HTML完全是两码事,HTML只不过是一种用于表现页 面内容的标记语言(Markup Language),而HTTP协议则允许浏览器从服务器获取各种类型的数据,HTML只是其中之一。事实上,HTTP协议定义了8中不同类型的请求,尽 管如此,我们最熟悉的可能还是下面两种:
GET,通过GET请求可以获取Web上的资源,每一个资源都由URL来唯一标识。
POST,通过发送一组数据到特定的URL来创建一个新资源。
PART II
你可能对我使用“资源”(Resource)这个词感到迷惑不解,事实上我第一次看到这个词时也跟你一样迷惑,但这正是REST的精髓所在,在REST的世界里,整个Web被看作一组资源的集合,而不是一张张的网页,这是什么意思呢?
昨天,我上当当买了几本书,又去维基百科查了几个词条,然后上新浪看了几条新闻,最后又在NBA网站上看了下骑士对马刺的比赛前瞻。
如果你想要理解REST,那么你就要转变你的思维,不要再认为以上这些东西都是一张张的网页,让我们以维基百科为例,我查阅的REST词条事实上并不是一张网页,它是一个资源,我们使用http://zh.wikipedia.org/wiki/REST访问这个资源,并取得了它的HTML表示,之所以是HTML,是因为浏览器只只是这种方式。
我承认这有些费解,http://zh.wikipedia.org/wiki/REST怎 么可能不是网页呢?事实上,确实不是,它是一个使用URL进行标识的资源,当我使用浏览器来访问它时,我得到了它的HTML表示,但维基百科可能还提供其 他形式的表示,比如一个PDF,一张JPG图片或者别的什么东西,而我之所以得到一个HTML,是因为我的Firefox发送了一个GET请求,并明确的 告诉了服务器,给我一个HTML表示。
再举个更浅显些的例子,比如我向南方航空定了张机票,他们可以通过HTML在浏览器中跟我确认,也可以发短信给我,或者发一封Mail,当然也可以选择最稳妥的方式,打个电话告诉我。事实上就是一种资源,多种表示。
希望经过这番唠叨,你能够理解我所说的,我的机票订单不止是个网页,它是一个资源,当然我可以选择通过浏览器以HTML的方式来查看它。
PART III
一旦你接受了Web就是个巨大的资源集合,这些资源可以使用任意多的方式来表示,而HTML只是其中一种时,你离真正掌握REST已经不远了,但在结束今 天的课程前,我还要在絮叨下:事实上,资源并不总是单个的东西,比如维基百科上介绍REST的文章,一张机票订单或者一堆NBA比赛数据,它也可以是一组 资源的集合,比如中国传统节日列表,你最好的朋友等等,它们都是资源。
现在,你应该已经理解了什么是资源,在下一节,我们将讲解如何通过HTTP来创建(Creation),读取(Reading),更新(Updating)和销毁(Destruction)一个资源。
通过上一讲,我认为你树立了这个概念:即Web其实是一组资源而不是网页的集合(如果你还不这么认为,那请你先返回再次阅读第一讲)。这一讲我们将从另一个侧面来讲解为什么要有REST?
面向对象设计与分析
如果你曾经学习过面向对象程序设计,那么你很可能会这样开始构建你的新程序:
首先,你需要定义你的问题域——你的程序要解决什么问题
然后,你会定义一个类,这个类的名字一般是名词
接着你会为这个类定义一些方法,方法的名字一般是动词
最用,通过调用其它类的方法,你的这个类顺利完成了它的使命
这看起来不错,事实上我曾经这么干了好多年,这种名词加动词的编程方法被成为“RPC”(远程过程调用),虽然我不明白那个Remote(远程)是指什么,但RPC的确是构建面向对象软件的一个重要方法,不过这种方式却并不适合Web开发。
让我们回到远古,假设现在是1992年(或者Web出现之前的随便什么日子),假设有这样的三家公司,他们需要开发这样三种应用:书籍贩卖,机票贩卖以及 卫星地图浏览。并且他们都遵照了面向对象的设计思想,同时出于长远考虑,他们都认为总有一天会有第三方的软件需要同他们的系统进行交互,因此,他们都实现 了他们各自的API。
现在,假设你的老板分配给你一个任务:为这三个系统设计一个统一的前端,你会怎么做呢?
我想你首先需要学习这三种完全不同的API,然后为每一个API设计一个UI控件,当用户操作UI控件时,对应的API就会被调用,你可能会通过你学到的一些设计模式知识来简化你的工作量,并使你的代码看起来尽可能酷一些。
无穷尽的API
当然这只是假设,但即使真的如此,在Web时代,你也不需要去学习那些无穷尽的糟糕API,你所要做的就是在你的电脑上安装一个浏览器,不是吗?浏览器对 于你将要访问的网站一无所知,但它却能够准确的返回你想要的,你可以通过它购买音乐,预定机票,甚至从任意远的距离来欣赏你家的屋顶。
这很神奇,不是吗?但是让我们设想一下,如果每个网站都有它们自己的API会是什么样子?如果你想在Amazon买本书,浏览器必须知道如何调用 Amazong.buy(),如果你想查看航班信息,那么浏览器需要知道如何调用UnitedAirlines.CheckFlights(),事实上, 这样通吃所有API的程序永远也不可能被开发出来。
所以这就决定了Web不可能是RPC式的,它只能是REST式的。
以资源为中心的设计
那么REST究竟是什么呢?按照维基百科的解释,REST是指Representational State Transfer。这是什么意思呢,简单的说,就是现在每个名词都不再拥有它们各自独一无二的动词了,在REST的世界里,所有名词拥有的动词都是一样 的,并且数量也很有限。换句话说,也就是所有的资源都提供了一组相同的API,这些API的实质就是允许随便什么客户端:
获取资源的某种表示
创建一个新资源
更新已存在的资源
销毁一个资源
等一下!那么究竟上面那个API可以让我“购买一本书”呢?搜索“下周二从纽约飞往洛杉矶的航班”又是哪个API完成的呢?
我们将在下一讲回答这个问题,但是如果你已经改变思维,不再认为”买书“就是一个网页,而是开始思考这其实是某个资源的创建,那么我想你其实应该已经知道答案了。
面向对象设计与分析
如果你曾经学习过面向对象程序设计,那么你很可能会这样开始构建你的新程序:
首先,你需要定义你的问题域——你的程序要解决什么问题
然后,你会定义一个类,这个类的名字一般是名词
接着你会为这个类定义一些方法,方法的名字一般是动词
最用,通过调用其它类的方法,你的这个类顺利完成了它的使命
这看起来不错,事实上我曾经这么干了好多年,这种名词加动词的编程方法被成为“RPC”(远程过程调用),虽然我不明白那个Remote(远程)是指什么,但RPC的确是构建面向对象软件的一个重要方法,不过这种方式却并不适合Web开发。
让我们回到远古,假设现在是1992年(或者Web出现之前的随便什么日子),假设有这样的三家公司,他们需要开发这样三种应用:书籍贩卖,机票贩卖以及 卫星地图浏览。并且他们都遵照了面向对象的设计思想,同时出于长远考虑,他们都认为总有一天会有第三方的软件需要同他们的系统进行交互,因此,他们都实现 了他们各自的API。
现在,假设你的老板分配给你一个任务:为这三个系统设计一个统一的前端,你会怎么做呢?
我想你首先需要学习这三种完全不同的API,然后为每一个API设计一个UI控件,当用户操作UI控件时,对应的API就会被调用,你可能会通过你学到的一些设计模式知识来简化你的工作量,并使你的代码看起来尽可能酷一些。
无穷尽的API
当然这只是假设,但即使真的如此,在Web时代,你也不需要去学习那些无穷尽的糟糕API,你所要做的就是在你的电脑上安装一个浏览器,不是吗?浏览器对 于你将要访问的网站一无所知,但它却能够准确的返回你想要的,你可以通过它购买音乐,预定机票,甚至从任意远的距离来欣赏你家的屋顶。
这很神奇,不是吗?但是让我们设想一下,如果每个网站都有它们自己的API会是什么样子?如果你想在Amazon买本书,浏览器必须知道如何调用 Amazong.buy(),如果你想查看航班信息,那么浏览器需要知道如何调用UnitedAirlines.CheckFlights(),事实上, 这样通吃所有API的程序永远也不可能被开发出来。
所以这就决定了Web不可能是RPC式的,它只能是REST式的。
以资源为中心的设计
那么REST究竟是什么呢?按照维基百科的解释,REST是指Representational State Transfer。这是什么意思呢,简单的说,就是现在每个名词都不再拥有它们各自独一无二的动词了,在REST的世界里,所有名词拥有的动词都是一样 的,并且数量也很有限。换句话说,也就是所有的资源都提供了一组相同的API,这些API的实质就是允许随便什么客户端:
获取资源的某种表示
创建一个新资源
更新已存在的资源
销毁一个资源
等一下!那么究竟上面那个API可以让我“购买一本书”呢?搜索“下周二从纽约飞往洛杉矶的航班”又是哪个API完成的呢?
我们将在下一讲回答这个问题,但是如果你已经改变思维,不再认为”买书“就是一个网页,而是开始思考这其实是某个资源的创建,那么我想你其实应该已经知道答案了。
LetRails 写道
通过上一讲,我们明白了为什么Web需要按照REST的方式来设计,而不是传统的面向对象编程的RPC方式,这一讲我们将通过一个实例来演示如何进行REST方式的Web设计,也就是让我们的设计变的RESTful。
航空公司的需求
我们假设你为一家航空公司工作,你的任务是为他们设计一个航班管理系统,它的功能包括:
允许公司员工通过Web前端来输入航班信息。航班信息包括航班的起飞和降落城市,以及起飞时间等。
允许客户通过手机查询他的航班信息。
允许第三方通过我们提供的API来获取我们的航班信息。
很没有难度,不是吗?如果你是个急性子,你甚至可能都顾不上将你无懈可击的设计转换成UML,就已经在你IDE的编辑框里输入了如下字符:
class FlightSchedule
def CancelFlight
......
但是慢着,在REST的世界里,我们不再需要操心这些,我们需要做的只有一件事情:
定义你的资源!
是的,就这一件,因为REST已经为我们定义好了用于操作这些资源的方法。
在这个例子里,我们首先会想到这几个资源:airports,airplanes,flights。当然可能还会有其它,但就让我们先从这几个开始吧!
我们首先要做的就是为这些资源分配URL,原则只有一个:尽可能的简单明了。
/airports,通过这个URL可以访问所有的机场资源
/airplanes,通过这个URL可以访问所有的飞机资源
/flights,通过这个URL可以访问所有航班资源
还有:
/airports/pudong,通过这个URL可以获取浦东机场的相关信息
/airplanes/ZJ3543,通过这个URL可以获取编号为ZJ3543的飞机信息
/flights/451,通过这个URL咋可以了解到航班451的起飞,降落城市已经起飞时间等信息。
方法已经准备好了
一旦你定义好了你的资源,整个设计也就完成了,因为,REST已经为你准备好了以下四个方法(并且不再需要其它的了):
GET,获取资源
POST,创建一个新资源
PUT,更新已存在的资源
DELETE,删除资源
通过HTTP调用这些方法
同样的,我们也不需要关心客户端如何来调用我们的方法,浏览器会帮我们搞定一切。
如果你仅仅只是在地址栏敲了个地址,然后按了下回车,浏览器会生成一条HTTP消息,并通过它来调用你输入的URL所代表的资源的GET方法。
如果你填写了一个表单,并点击了提交按钮,那么浏览器会将你填在表单中的信息组装成一条HTTP POST消息,并通过它来调用你想访问资源的POST方法。
但不幸的是,由于HTML的限制,目前你无法通过浏览器来调用资源的PUT和DELETE方法,不过这不重要,GET和POST对我们已经足够了。
好了,我们的基于REST的设计就这么完成了,下一讲,我们将演示如何使用Rest on Rails来快速优美的实现我们的设计。
航空公司的需求
我们假设你为一家航空公司工作,你的任务是为他们设计一个航班管理系统,它的功能包括:
允许公司员工通过Web前端来输入航班信息。航班信息包括航班的起飞和降落城市,以及起飞时间等。
允许客户通过手机查询他的航班信息。
允许第三方通过我们提供的API来获取我们的航班信息。
很没有难度,不是吗?如果你是个急性子,你甚至可能都顾不上将你无懈可击的设计转换成UML,就已经在你IDE的编辑框里输入了如下字符:
class FlightSchedule
def CancelFlight
......
但是慢着,在REST的世界里,我们不再需要操心这些,我们需要做的只有一件事情:
定义你的资源!
是的,就这一件,因为REST已经为我们定义好了用于操作这些资源的方法。
在这个例子里,我们首先会想到这几个资源:airports,airplanes,flights。当然可能还会有其它,但就让我们先从这几个开始吧!
我们首先要做的就是为这些资源分配URL,原则只有一个:尽可能的简单明了。
/airports,通过这个URL可以访问所有的机场资源
/airplanes,通过这个URL可以访问所有的飞机资源
/flights,通过这个URL可以访问所有航班资源
还有:
/airports/pudong,通过这个URL可以获取浦东机场的相关信息
/airplanes/ZJ3543,通过这个URL可以获取编号为ZJ3543的飞机信息
/flights/451,通过这个URL咋可以了解到航班451的起飞,降落城市已经起飞时间等信息。
方法已经准备好了
一旦你定义好了你的资源,整个设计也就完成了,因为,REST已经为你准备好了以下四个方法(并且不再需要其它的了):
GET,获取资源
POST,创建一个新资源
PUT,更新已存在的资源
DELETE,删除资源
通过HTTP调用这些方法
同样的,我们也不需要关心客户端如何来调用我们的方法,浏览器会帮我们搞定一切。
如果你仅仅只是在地址栏敲了个地址,然后按了下回车,浏览器会生成一条HTTP消息,并通过它来调用你输入的URL所代表的资源的GET方法。
如果你填写了一个表单,并点击了提交按钮,那么浏览器会将你填在表单中的信息组装成一条HTTP POST消息,并通过它来调用你想访问资源的POST方法。
但不幸的是,由于HTML的限制,目前你无法通过浏览器来调用资源的PUT和DELETE方法,不过这不重要,GET和POST对我们已经足够了。
好了,我们的基于REST的设计就这么完成了,下一讲,我们将演示如何使用Rest on Rails来快速优美的实现我们的设计。
写道
通过上一讲我们了解到,RESTful设计的关键就是定义系统中的资源,这一讲我们将学习在Rails中,如何将请求路由到我们的资源,以及我们应该如何来处理它。
不过,有一点需要先说明:REST并不是Rails的一部分,在Rails出现之前,REST的概念已经存在很多年了,并且REST的应用也并不局限于Web,事实上,它也可以应用到其它各种应用软件的开发中。
资源就是控制器
在我们正式开始之前,我们需要首先明确,在Rails中,资源和model并不总是一对一的关系,有时资源仅仅只是你应用逻辑中的一个实体的抽象,并不需要 映射到你的数据库。但资源跟控制器总是一对一的,也就是每个资源都必须有一个与它相对应的控制器,并且你需要重新理解控制器,现在控制器只是REST接口 的具体实现,它的全部作用就是根据客户的请求返回资源的某种表示(HTML,XML等)。
所以,就像第2章讲的,我们不在需要去设计那无穷尽的API了,现在我们的控制器只需要定义7个方法:
show,处理针对单个资源的GET请求
create,处理POST请求,并将创建一个新资源
update,处理PUT请求,并更新指定的资源
destroy,处理DELETE请求,销毁一个资源
index,处理针对多个资源的GET请求
new,GET请求,返回一个用于创建资源的表单,
edit,GET请求,返回一个用于更新资源的表单
Rails 会帮助我们将用户的请求路由到某个合适的方法,当然,你并不需要实现这全部的7个方法,如果你的系统不允许用户创建和修改资源,那么你只需要实现 index和show方法就可以了。
不过更有可能的一种情况是你觉得这7个方法根本不够,你当然可以选择向控制器添加新的方法,但这其实是因为你的设计遗漏了一些资源,因为我建议,在你向控制器添加新方法之前,最好先重新考虑下你的设计。
方法已经定义好了,下一步的任务就是将用户的请求路由到指定的方法,在router.rb中,你可能会看到这样的路由:
map.connect '/airports/:action/:id', :controller = 'airports'
这条语句将映射/airports/open/45到airports控制器的open方法,你可以通过params[:id]获取URL中的参数45。但是REST路由有些特殊,它需要同时考虑URL和请求的类型,因此同样是发往/airports/1的请求,如果是GET请求,它需要被路由到airports的show方法,而DELETE请求则需要被路由到DELETE方法。
不过幸运的是,从Rails1.2开始,我们不再需要通过map.connect来手动的配置REST路由,map.resources会帮我们搞定一切:
map.resources 'airports'
这句话将创建如下的路由规则:
针对/airports/ 的POST请求将被路由到create方法
针对/airports/1 的GET请求将被路由到show方法
针对/airports/1的PUT请求被路由到update方法
针对/airports/1 的DELETE请求被路由到destroy方法
针对/airports/ 的GET请求被路由到index方法
针对/airports/new 的GET请求被路由到new方法
针对/airports/1;edit 的GET请求被路由到edit方法
注意:最后一条逗号分隔的URL看起来很丑陋,但它们在Rails1.2.3中是合法的,不过不用苦恼,它们将在Rails2.0中被去除
现在我们已经完成了URL的路由,下面我们需要做的就是实现这些方法:
不过先别着急着码代码,从Rails1.2开始,我们有了一个新的生成器(generator):scaffold_resource,使用它我们可以很轻松的生成一个符合REST规范的Rails框架,它包含:
资源所对应的model
资源的migration文件
资源所对应的控制器,控制器已经包含了REST所需的7个方法的实现
这7个方法所对应的RHTML文件
一条映射用户请求的路由
让我们仍然从第三讲的例子开始,首先创建一个新程序,然后为它添加一个airport资源:
D:\study>rails REST
D:\study>cd REST
D:\study\REST>ruby script/generate scaffold_resource airport name:string designator:string
修改database.yml文件,设置好你的数据库链接,然后执行:
D:\study\REST>rake db:migrate
D:\study\REST>ruby script/server
现在定位你的浏览器到http://localhost:3000/airports/new,你应该已经可以创建一个新机场了,是不是很神奇?现在,让我们来看看airports_controller.rb,所有的东西都在那了。
你应该会在控制器代码中看到一些奇怪的respond_to块,这正是我们整个REST实现的关键所在,我们将在下一讲详细探讨respond_to的细节。
不过,有一点需要先说明:REST并不是Rails的一部分,在Rails出现之前,REST的概念已经存在很多年了,并且REST的应用也并不局限于Web,事实上,它也可以应用到其它各种应用软件的开发中。
资源就是控制器
在我们正式开始之前,我们需要首先明确,在Rails中,资源和model并不总是一对一的关系,有时资源仅仅只是你应用逻辑中的一个实体的抽象,并不需要 映射到你的数据库。但资源跟控制器总是一对一的,也就是每个资源都必须有一个与它相对应的控制器,并且你需要重新理解控制器,现在控制器只是REST接口 的具体实现,它的全部作用就是根据客户的请求返回资源的某种表示(HTML,XML等)。
所以,就像第2章讲的,我们不在需要去设计那无穷尽的API了,现在我们的控制器只需要定义7个方法:
show,处理针对单个资源的GET请求
create,处理POST请求,并将创建一个新资源
update,处理PUT请求,并更新指定的资源
destroy,处理DELETE请求,销毁一个资源
index,处理针对多个资源的GET请求
new,GET请求,返回一个用于创建资源的表单,
edit,GET请求,返回一个用于更新资源的表单
Rails 会帮助我们将用户的请求路由到某个合适的方法,当然,你并不需要实现这全部的7个方法,如果你的系统不允许用户创建和修改资源,那么你只需要实现 index和show方法就可以了。
不过更有可能的一种情况是你觉得这7个方法根本不够,你当然可以选择向控制器添加新的方法,但这其实是因为你的设计遗漏了一些资源,因为我建议,在你向控制器添加新方法之前,最好先重新考虑下你的设计。
方法已经定义好了,下一步的任务就是将用户的请求路由到指定的方法,在router.rb中,你可能会看到这样的路由:
map.connect '/airports/:action/:id', :controller = 'airports'
这条语句将映射/airports/open/45到airports控制器的open方法,你可以通过params[:id]获取URL中的参数45。但是REST路由有些特殊,它需要同时考虑URL和请求的类型,因此同样是发往/airports/1的请求,如果是GET请求,它需要被路由到airports的show方法,而DELETE请求则需要被路由到DELETE方法。
不过幸运的是,从Rails1.2开始,我们不再需要通过map.connect来手动的配置REST路由,map.resources会帮我们搞定一切:
map.resources 'airports'
这句话将创建如下的路由规则:
针对/airports/ 的POST请求将被路由到create方法
针对/airports/1 的GET请求将被路由到show方法
针对/airports/1的PUT请求被路由到update方法
针对/airports/1 的DELETE请求被路由到destroy方法
针对/airports/ 的GET请求被路由到index方法
针对/airports/new 的GET请求被路由到new方法
针对/airports/1;edit 的GET请求被路由到edit方法
注意:最后一条逗号分隔的URL看起来很丑陋,但它们在Rails1.2.3中是合法的,不过不用苦恼,它们将在Rails2.0中被去除
现在我们已经完成了URL的路由,下面我们需要做的就是实现这些方法:
不过先别着急着码代码,从Rails1.2开始,我们有了一个新的生成器(generator):scaffold_resource,使用它我们可以很轻松的生成一个符合REST规范的Rails框架,它包含:
资源所对应的model
资源的migration文件
资源所对应的控制器,控制器已经包含了REST所需的7个方法的实现
这7个方法所对应的RHTML文件
一条映射用户请求的路由
让我们仍然从第三讲的例子开始,首先创建一个新程序,然后为它添加一个airport资源:
D:\study>rails REST
D:\study>cd REST
D:\study\REST>ruby script/generate scaffold_resource airport name:string designator:string
修改database.yml文件,设置好你的数据库链接,然后执行:
D:\study\REST>rake db:migrate
D:\study\REST>ruby script/server
现在定位你的浏览器到http://localhost:3000/airports/new,你应该已经可以创建一个新机场了,是不是很神奇?现在,让我们来看看airports_controller.rb,所有的东西都在那了。
你应该会在控制器代码中看到一些奇怪的respond_to块,这正是我们整个REST实现的关键所在,我们将在下一讲详细探讨respond_to的细节。
写道
通过上一讲,我们已经对REST on Rails的基本框架有所了解,但是它是如何实现根据客户端的请求类型来返回不同类型的资源表示的呢?这就是我们这一讲所要讲的,秘密就在于respond_to。
首先让我们来看看我们在上一讲中生成的airports控制器的代码:
class AirportsController < ApplicationController
def index
@airports = Airport.find :all
respond_to do |format|
format.html # do nothing, allow Rails to render index.rhtml
format.js # do nothing, allow Rails to render index.rjs
format.xml { render "http://lr.zoomtype.info/wp-includes/images/smilies/icon_mad.gif" alt=":x" class="wp-smiley"> ml => @airports.to_xml }
end
end
end
我们以index方法为例,其它方法的实现大同小异。第一行代码很容易理解,获取所有的机场信息,但是接下来的代码就比较费解了,而这也正是REST on Rails的关键所在,那个respond_to是做什么的呢?
我们知道,在HTTP协议中,客户端会在他们的HTTP首部包含一些元信息(meta-information),这些元信息按照“字段:值”的方式来组织,HTTP协议预定义了很多标准字段,其中的一个字段就是“Accept-type“,它代表发送请求的客户端能够支持或者说理解的资源表示类型,如果没有为这个键指定值,服务端会认为客户端能够理解标准的HTML文档,当然,客户端可以为这个字段指定任意的符合MIME规范的类型值,假设客户端设置这个字段为”Accept-Type: text/xml“,则服务端必须返回资源的XML表示。
所以respond_to事实上就是根据HTTP首部的Accept-Type字段来决定向客户端返回那种类型的资源表示,如果不使用respond_to,我们的实现可能会是这个样子:
class AirportsController < ApplicationController
# Pretend that Rails will call our index action,
# and will pass in the value of the Accept-Type header
def index(client_format)
@airports = Airport.find :all
if client_format == “text/html”
# TO DO: render the default template
elsif client_format == “application/javascript”
# TO DO: return some javascript
elsif client_format == “application/xml” || client_format == “text/xml”
# TO DO: return some XML back the client
# … more elsif statements here for each MIME type you want to support
end
end
end
这很丑陋,不是吗?但它却相当直观,我想respond_to的作者可能最初也是这么写的,或者这段代码至少在他的脑海中闪现过,但立刻就被他否定了,因为它实在是太蹩脚了,所以他对这段代码进行了重整,于是有了respond_to。
respond_to do |format|
format.html # do nothing, allow Rails to render index.rhtml
format.js # do nothing, allow Rails to render index.rjs
format.xml { render "http://lr.zoomtype.info/wp-includes/images/smilies/icon_mad.gif" alt=":x" class="wp-smiley"> ml => @airports.to_xml }
end
但是Block内的代码看起来仍然比较古怪,事实上,如果我们理解了respond_to的设计思想,那么这段代码看起来就非常理所当然了。
respond_to基于这样的思想设计的,你不需要知道客户端的请求到底是那种类型,你只需要告诉Rails你准备支持那些类型的请求,Rails会自动帮你处理剩下的事情。
所以,这里我们告诉Rails,对于HTML和JS类型的请求,采用默认的实现,而对XML则使用我们在Block内提供的实现。
指南到这里就结束了,篇幅有限,我们只能对REST的基本概念和它在Rails中的简单实现做一个基本的介绍,REST on Rails的世界还有更多的东西等着你去探索。
我建议你尝试动手创建一个Rails应用,然后试试scaffold_resource生成器,阅读并试着理解生成的代码,然后尝试修改view和controller,事实上,比你想象的要简单的多,不是吗?
祝你好运同时期待你的反馈!
首先让我们来看看我们在上一讲中生成的airports控制器的代码:
class AirportsController < ApplicationController
def index
@airports = Airport.find :all
respond_to do |format|
format.html # do nothing, allow Rails to render index.rhtml
format.js # do nothing, allow Rails to render index.rjs
format.xml { render "http://lr.zoomtype.info/wp-includes/images/smilies/icon_mad.gif" alt=":x" class="wp-smiley"> ml => @airports.to_xml }
end
end
end
我们以index方法为例,其它方法的实现大同小异。第一行代码很容易理解,获取所有的机场信息,但是接下来的代码就比较费解了,而这也正是REST on Rails的关键所在,那个respond_to是做什么的呢?
我们知道,在HTTP协议中,客户端会在他们的HTTP首部包含一些元信息(meta-information),这些元信息按照“字段:值”的方式来组织,HTTP协议预定义了很多标准字段,其中的一个字段就是“Accept-type“,它代表发送请求的客户端能够支持或者说理解的资源表示类型,如果没有为这个键指定值,服务端会认为客户端能够理解标准的HTML文档,当然,客户端可以为这个字段指定任意的符合MIME规范的类型值,假设客户端设置这个字段为”Accept-Type: text/xml“,则服务端必须返回资源的XML表示。
所以respond_to事实上就是根据HTTP首部的Accept-Type字段来决定向客户端返回那种类型的资源表示,如果不使用respond_to,我们的实现可能会是这个样子:
class AirportsController < ApplicationController
# Pretend that Rails will call our index action,
# and will pass in the value of the Accept-Type header
def index(client_format)
@airports = Airport.find :all
if client_format == “text/html”
# TO DO: render the default template
elsif client_format == “application/javascript”
# TO DO: return some javascript
elsif client_format == “application/xml” || client_format == “text/xml”
# TO DO: return some XML back the client
# … more elsif statements here for each MIME type you want to support
end
end
end
这很丑陋,不是吗?但它却相当直观,我想respond_to的作者可能最初也是这么写的,或者这段代码至少在他的脑海中闪现过,但立刻就被他否定了,因为它实在是太蹩脚了,所以他对这段代码进行了重整,于是有了respond_to。
respond_to do |format|
format.html # do nothing, allow Rails to render index.rhtml
format.js # do nothing, allow Rails to render index.rjs
format.xml { render "http://lr.zoomtype.info/wp-includes/images/smilies/icon_mad.gif" alt=":x" class="wp-smiley"> ml => @airports.to_xml }
end
但是Block内的代码看起来仍然比较古怪,事实上,如果我们理解了respond_to的设计思想,那么这段代码看起来就非常理所当然了。
respond_to基于这样的思想设计的,你不需要知道客户端的请求到底是那种类型,你只需要告诉Rails你准备支持那些类型的请求,Rails会自动帮你处理剩下的事情。
所以,这里我们告诉Rails,对于HTML和JS类型的请求,采用默认的实现,而对XML则使用我们在Block内提供的实现。
指南到这里就结束了,篇幅有限,我们只能对REST的基本概念和它在Rails中的简单实现做一个基本的介绍,REST on Rails的世界还有更多的东西等着你去探索。
我建议你尝试动手创建一个Rails应用,然后试试scaffold_resource生成器,阅读并试着理解生成的代码,然后尝试修改view和controller,事实上,比你想象的要简单的多,不是吗?
祝你好运同时期待你的反馈!
评论
2 楼
Hooopo
2009-08-25
引用
web services的优点和缺点都非常突出,这个不是本文的要点,不做具体分析。这里唯一要强调的是SOAP协议并不依赖于HTTP。事实上SOAP协议可以走很多底层协议,例如SMTP协议,Jabber协议等等。
REST也是一种分布式系统的架构风格,那么REST和上面这些分布式架构有哪些明显的区别呢?
1) REST走的是HTTP协议,并且充分利用或者说极端依赖HTTP协议
Corba和EJB是采用专有的二进制协议,SOAP可以但不依赖HTTP,并且仅仅使用HTTP POST。
2) REST是基于HTTP抽象资源的分布式调用,换句话来说,就是分布式调用是绑定在资源的操作上面的。
REST也是一种分布式系统的架构风格,那么REST和上面这些分布式架构有哪些明显的区别呢?
1) REST走的是HTTP协议,并且充分利用或者说极端依赖HTTP协议
Corba和EJB是采用专有的二进制协议,SOAP可以但不依赖HTTP,并且仅仅使用HTTP POST。
2) REST是基于HTTP抽象资源的分布式调用,换句话来说,就是分布式调用是绑定在资源的操作上面的。
1 楼
Hooopo
2009-08-25
引用
REpresentational State Transfer(REST) 代表性状态传输
REST是WEB服务的一种架构,简单的说就是通过HTTP协议提供XML数据。最常见的应用就是RSS.
REST的基本规则:
1、所有可区分的实体都是资源,这些资源可以是一个XML文档,或者是一个HTML页面来进行描述(Representation ). 补充:鉴于xml的结构化,跨平台等等特性,建议所有的资源都通过xml进行描述
2、每个资源通过一个唯一的URL进行定义
3、WEB服务返回的数据应该包含其它数据的链接地址(URL). 也就是说,把要提供的数据设计成一个信息网络
4、服务提供方维护一组资源,并公开一组基本操作来执行以下任务:
检索资源(HTTP GET)
创建新资源 (HTTP POST)
修改资源 (HTTP POST)
删除资源 (HTTP POST)
REST是WEB服务的一种架构,简单的说就是通过HTTP协议提供XML数据。最常见的应用就是RSS.
REST的基本规则:
1、所有可区分的实体都是资源,这些资源可以是一个XML文档,或者是一个HTML页面来进行描述(Representation ). 补充:鉴于xml的结构化,跨平台等等特性,建议所有的资源都通过xml进行描述
2、每个资源通过一个唯一的URL进行定义
3、WEB服务返回的数据应该包含其它数据的链接地址(URL). 也就是说,把要提供的数据设计成一个信息网络
4、服务提供方维护一组资源,并公开一组基本操作来执行以下任务:
检索资源(HTTP GET)
创建新资源 (HTTP POST)
修改资源 (HTTP POST)
删除资源 (HTTP POST)
发表评论
-
新博客
2012-04-23 20:47 1734https://db-china.org -
Draper: View Models for Rails
2011-10-07 01:19 2268Draper是一个Ruby gem,它让Rails model ... -
Active Record batch processing in parallel processes
2011-10-07 01:20 2270Active Record 提供 find_each来分批处理 ... -
答复: Sinatra:一个可以作为Rails有益补充的框架. 简洁而不简单
2010-04-07 18:21 1655既然是这么简单的事情,用rack写也比较有趣: 一共5个文件, ... -
mass-assignment protection【?】
2010-03-18 18:31 101Attributes named in this ma ... -
基于jquery和mini_magick的图片裁剪
2009-12-04 19:32 3824jquery imgAeraSelect插件地址:http:/ ... -
Showing SQL statements in the Rails console
2009-10-23 13:29 19801.windows下创建_irbrc文件,并设置环境变量 2. ... -
Security Tips
2009-10-01 17:28 974Hackers Love Mass Assignment 对于 ... -
HTTP request 相关
2009-09-25 13:52 1256>> app.request.query_para ... -
可定制的Rails错误回显
2009-09-16 09:30 2829通常rails页面的错误信息提示都是放在首部用 error_m ... -
用户注册邮件激活
2009-09-04 17:26 50201.网站用户相关表中有一个字段用来记录用户帐号是否激活。 ... -
check-if-record-was-just-destroyed-in-rails
2009-08-20 11:02 1018问题: So there is record.new_ ... -
Using indexes in rails: Index your associations
2009-08-19 14:23 1151Many rails developers are g ... -
委托 in rails
2009-08-09 01:16 1166Delegation is a feature Rails ... -
还是习惯用法好啊。。。
2009-08-08 09:00 1219在看ASCIICast的rails示例里面看到这样的代码: ... -
弄了个小论坛...
2009-08-07 05:27 1058http://github.com/hooopo/Rails- ... -
I18n for Rails之hello world
2009-08-01 04:52 1182平台:rails 2.3.2 ruby 1.8.6 1.rai ... -
Using with_scope
2009-07-29 01:57 854In this episode we’ll talk abou ... -
Move Find Into Model
2009-07-29 01:52 981下面是在控制器里面通过model查找未完成的任务: c ... -
Find Through Association
2009-07-29 01:39 984Project model has_many tasks: ...
相关推荐
在本篇内容中,我们将深入探讨如何利用Ruby on Rails(简称Rails)这一强大的Web应用程序框架来构建可伸缩且易于维护的RESTful API。Rails以其简洁优雅的语法、高效的开发速度以及良好的社区支持而闻名,这使得它...
### 应用Rails进行REST开发 #### 1.1 什么是REST? REST(Representational State Transfer),这是一种由Roy Fielding在他的博士论文中提出的架构风格。REST的核心思想是通过标准HTTP协议中的GET、POST、PUT、...
Ruby on Rails是一个突然流行...本文介绍Rails中的Web服务,重点放在一个名为Representational State Transfer (REST)的策略上。本文介绍了如何在Ruby on Rails中添加REST风格的Web服务,并从Ruby和Java代码调用服务。
《Rails 3 in Action》是2011年由Ryan Bigg撰写的一本关于Ruby on Rails框架的权威指南,专门针对当时最新的Rails 3.1版本进行了深入解析。这本书旨在帮助开发者充分利用Rails 3.1的强大功能,提升Web应用开发的效率...
### Rails 4 in Action, 第二版:关键知识点解析 #### 一、Rails 4简介与新特性 **Rails 4 in Action, 第二版** 是一本深入介绍Ruby on Rails框架的专业书籍。该书由Ryan Bigg、Yehuda Katz、Steve Klabnik和...
标题“Rails学习资料”表明这是一份关于Rails框架的学习资源,可能包含教程、示例代码、最佳实践等内容,适合初学者和有一定经验的开发者。描述中的“仅仅三分,就可以帮助你搭好框架”,暗示这份资料可能包含快速...
总的来说,"rails资料集合最新"提供的资源涵盖了Rails 3的基础学习到实际项目实践,对于想要深入了解或提升Rails技能的开发者来说,是一份非常有价值的参考资料。通过阅读文档、教程并动手实践博客应用,可以全面...
Rubyisms in Rails
Since the API documentation is liberally licensed (just like the rest of Rails), there are some sections of the book that draw from the API documentation. But in practically all of those cases, the ...
### Ruby on Rails 2.1 新特性详解 #### 引言 自2004年7月David Heinemeier Hansson公开发布Ruby on Rails框架以来,这一轻量级且功能强大的Web开发框架迅速赢得了全球开发者们的青睐。经过三年多的发展与优化,在...
### RAILS2.1的中文版资料:新特性与改进详解 #### 概述 《RAILS2.1的中文版资料》是一份针对Ruby on Rails 2.1版本的详细介绍文档,由Carlos Brando和Marcos Tapajós共同编写,并由中国Rails社区成员翻译成中文...
WeChat in Rails 的 API、命令和消息处理
《Rails101_by_rails4.0》是一本专注于Rails 4.0.0版本和Ruby 2.0.0版本的自学教程书籍,它定位于中文读者,旨在成为学习Rails框架的参考教材。Rails(Ruby on Rails)是一个采用Ruby语言编写的开源Web应用框架,它...
唔,1分应该还是有人下的吧,共同学习进步,Ruby on Rails is an open source web framework.... "Rails 4 in Action" is a fully-revised second edition of "Rails 3 in Action." This hands-on, compreh...
总结来说,"使用rails编写REST风格的web应用"涉及的内容包括Rails框架基础、MVC模式的理解、RESTful设计原则的应用、路由配置、控制器和模型的编写、视图渲染以及相关的测试和安全措施。学习这部分内容将使开发者...