2.2 REST 架构

概要:

本课时结合 Rails 路由(routes),详解 Rails 如何实现 REST 架构。

知识点:

  1. REST
  2. CRUD

正文

2.2.1 什么是 REST

REST,Representational State Transfer, 更准确地表述应该是:具有代表性的状态转移。这是一种软件架构风格。说它是风格,表明它不具备约束。你可以破坏它,不按照它的风格去实现。但是,REST 拥有简洁的设计理念,按照它的设计可以在开发中获得益处。

Rails 是按照 REST 风格设计的,从1.2版本起,Rails 就开始按照 REST 架构管理资源。

如何管理呢?Rails 从以下三个方面对资源进行定义:

  1. 直观简短的资源地址:URI,比如:http://example.com/resources/。
  2. 可传输的资源:Web 服务接受与返回的互联网媒体类型,比如:JSON,XML ,YAML 等。
  3. 对资源的操作:Web 服务在该资源上所支持的一系列请求方法(比如:POST,GET,PUT或DELETE)。

在我们的代码里,我想你已经在上一节创建的项目里体验到了如何增加,修改,和删除一个商品。

以上引述于http://zh.wikipedia.org/wiki/REST,并结合 Rails 做了解释。这里还有一篇文章,推荐阅读:如何获取(GET)一杯咖啡——星巴克REST案例分析

REST是资源管理的模式,和 SOAP 和 XML-RPC 相比更加简洁,下一节,我们介绍Rails 是如何管理资源的。

2.2.2 CRUD,资源的增删改查

首先,我们在 Rails 中定义一个资源,我们在 routes 中使用 resources 这个方法:

  1. Rails.application.routes.draw do
  2. ...
  3. resources :products

我们运行这个命令:

  1. % rake routes | grep product
  2. products GET /products(.:format) products#index
  3. POST /products(.:format) products#create
  4. new_product GET /products/new(.:format) products#new
  5. edit_product GET /products/:id/edit(.:format) products#edit
  6. product GET /products/:id(.:format) products#show
  7. PATCH /products/:id(.:format) products#update
  8. PUT /products/:id(.:format) products#update
  9. DELETE /products/:id(.:format) products#destroy

Rails 为我们提供了7个方法,他们在 app/controllers/products_controller.rb 这个文件中。

当我们 GET /products 这个地址时,调用的是 index 方法,当我们 POST /products 地址时,Rails 会按照 REST 的模式,把请求转入到 create 方法内。我们看一下这个表:

HTTP 请求方法在RESTful Web 服务中的典型应用

资源 GET PUT POST DELETE
一组资源的URI,比如http://example.com/resources/ 列出 URI,以及该资源组中每个资源的详细信息(后者可选)。 使用给定的一组资源替换当前整组资源。 在本组资源中创建/追加一个新的资源。 该操作往往返回新资源的URL。 删除整组资源。
单个资源的URI,比如http://example.com/resources/142 获取 指定的资源的详细信息,格式可以自选一个合适的网络媒体类型(比如:XML、JSON等) 替换/创建 指定的资源。并将其追加到相应的资源组中。 把指定的资源当做一个资源组,并在其下创建/追加一个新的元素,使其隶属于当前资源。 删除指定的元素。

所以,向 PATCHPUT 的地址是一个具体的资源,比如 /products/1,而 Rails 会把请求转移到 update 方法中。值得注意的是:在之前的 Rails 版本中,用的是 PUT 动作,4.0 后引入PATCH,稍微不同的是,patch 可以表示更新或局部更新,但在使用上,和 PUT 无异。[1]

:format 表示我们可以接受和响应对应的 format 请求。比如 /products/1 响应的是 html,而 /products/1.json 响应的是 json。

我们可以关闭这种响应,只需要 resources :products, format: false

或者更改响应,只接受和响应 json,如:resources :products, format: 'json'

在实践中,这对 API 的设计非常方便,比如页面上 ajax 调用 /api/users/1/status,约束它只返回 json 格式。

从现在开始,我们的代码主要集中在 app 文件夹内。下一节,我们将深入 Rails 的 routes 中,看看实践中经常遇到的情况,以及如何解决。你也可以请先阅读以下 Rails 手册 中的 routes 章节。

阅读

REST服务开发实战

为啥REST如此重要?