Rest Ruby On Rails

Preview:

DESCRIPTION

 

Citation preview

RESTREST & & RRuby uby oon n RRailsails

伍 少 坤shaokun@kudelabs.com

关于 关于 Kude LabsKude Labs

• 博客 http://kudelabs.com

• 专注于 Web Applications– Schedule.ph– PRDGuide.com– FriendsMap.net

• Web Wednesday Web Wednesday 活动活动http://kudelabs.com/category/web-wednesday-guangzhou

R E S TR E S T

我将要分享的……我将要分享的……

1. REST—— 标准、架构或者理念?– Resource– CRUD– HTTP Verb

2. Ruby on Rails

3. RESTful Login & Search?

4. Twitter & Facebook API

5. Tips

6. Q & A

RESTREST

• ReRepresentational SState TTransfer

– Client-server

– Stateless 无状态

– Cacheable 可缓存

– Layered system 负载均衡、共享内存

– Code on Demand* 临时扩展客户端功能

– Uniform interface 简化、去耦

一种抽象的概念、架构蓝图一种抽象的概念、架构蓝图Just an Architecture, Not a Standard or ProtocolJust an Architecture, Not a Standard or Protocol

描述基于互联网的分布式系统描述基于互联网的分布式系统Describe Internet Based Remote SystemDescribe Internet Based Remote System

RRemote emote PProcedure rocedure CCallsalls

• 一种分布式函数调用接口

• SOAP<?xml version=“1.0” encoding=“UTF-8”?>

<soap:Envelope xmlns:soap=“http://schemas.xmlsoap.org/soap/envelope/”>

<soap:Body>

<gs:doGoogleSearch xmlns:gs=“urn:GoogleSearch”>

<q>REST</q>

</gs:doGoogleSearch>

</soap:Body>

</soap:Envelope>

• Facebook API 、 Flickr API 、淘宝 API– http://api.flickr.com/services/rest/?method=flickr.photos.search

– http://gw.api.tbsandbox.com/router/rest?method=taobao.taobaoke.items.get

REST REST vsvs RPC RPC

• RPC– 允许定义任意的程序接口

• getUsers()

• getNewUsersSince(date)

• savePurchaseOrder()

• …

– 大多数通过 POST 进行通讯– 忽略 HTTP 现有功能

• Authentication

• Caching

• Content type

– SOAP 一种基于 HTTP 的通讯协议

• REST– 接口局限于现有的、标准的 H

TTP 操作• GET

• POST

• PUT

• DELETE

– 一种架构,而非协议– 充分利用 HTTP 协议– 交互的核心是 Stateful Resour

ces ,而非 Messages 或者 Operations

ResourceResourceCRUDCRUD

HTTP VerbHTTP Verb

ResourceResource

• Resouce 并不是数据• 而是数据 + 特定的表现形式 (representation)

– 所有事物都可以被抽象为 Resource – 每个 Resource 对应一个唯一的 URL – 通过 generic connector interface (HTTP) 进行操作– 对 Resource 的操作不会改变 URL– 所有的操作都是 Stateless

CRUD & HTTP VerbCRUD & HTTP Verb

• 对于 Resource 的操作 Create 、 Read 、 Update 和 Delete

• HTTP Verb– curl -X GET http://example.com/projects

– curl -X DELETE http://example.com/projects/1

HTTPHTTP CRUDCRUD SQLSQL

POST CREATE INSERT

GET READ SELECT

PUT UPDATE UPDATE

DELETE DELETE DELETE

REST Ruby on RailsREST Ruby on Rails

Ruby on RailsRuby on Rails

• 基于动态编程语言 Ruby

• MVC 架构 MModel-VView-CController

• 专注于 Web Application 的开发框架

• 从 v1.2.x 起支持 REST 架构

• v3 beta 可能在 1 月底发布!

REST Ruby on RailsREST Ruby on Rails

• 7 个 Controller 的 Action :– Index– Show– New– Edit– Create– Update– Destroy

• 4 个 HTTP Verb :– GET– POST– PUT– DELETE

HTTP VerbHTTP Verb URL with RESTURL with REST ActionAction URL without RESTURL without REST

GET /projects/1 show GET /projects/show/1

DELETE /projects/1 destroy GET /projects/destroy/1

PUT /projects/1 update POST /projects/update/1

POST /projects create POST /projects/create

class UsersController < ApplicationController # GET /users/1 def show() end

# POST /users def create() end

# PUT /users/1 def update() end

# DELETE /users/1 def destroy() endend

class UsersController < ApplicationController # GET /users/new def new; end

# GET /users/1/edit def edit; end

# GET /users def index; end

# GET /users/1 def show; end

# POST /users def create; end

# PUT /users/1 def update; end

# DELETE /users/1 def destroy; endend

User + Group = ?User + Group = ?

数据表结构

User 拥有很多 Groups

Group 拥有很多 Users

Users UsersGroups Groups1 N N 1

class Group < ActiveRecord::Base has_many :users_groups has_many :users, :through => :users_groupsend

class User < ActiveRecord::Base has_many :users_groups has_many :groups, :through => :users_groupsend

class UsersGroups < ActiveRecord::Base belongs_to :groups belongs_to :usersend

用例 Use CaseUser join Group

User leave Group

UsersControllerjoin_group()

# POST /users/1/join_group?group_id=2

leave_group()

# POST /users/1/leave_group?group_id=2

GroupsControlleradd_user()

# POST /groups/1/add_user?user_id=2

remove_user()

# POST /groups/1/remove_user?user_id=2

UserUser + + GroupGroup = = UserGroupUserGroup

MembershipMembership

class Group < ActiveRecord::Base has_many :memberships has_many :users, :through => :membershipsend

class User < ActiveRecord::Base has_many :memberships has_many :groups, :through => :membershipsend

class Membership < ActiveRecord::Base belongs_to :groups belongs_to :usersend

MembershipsControllercreate()# INSERT INTO "memberships" ("group_id", "user_id") VALUES(2, 1)

# POST /memberships?user_id=1&group_id=2

destroy()# DELETE FROM "memberships" WHERE "id" = 1

# DELETE /memberships/3

mine typesmine types

class UsersController < ApplicationController # GET /users # GET /users.xml def index @users = User.all

respond_to do |format| format.html # index.html.erb format.js { render :json => @users } format.xml { render :xml => @users } fomrat.atom do render :action => “atom”, :content_type => Mine::ATO

M end end endend

• GET /users => HTML

• GET /users.xml => XML

• Accept: text/javascriptGET /users => json

• Accept: text/htmlGET /users.xml => XML

Nested ResrouceNested Resrouce

GET /groups

GET /groups/1

DELETE /groups/1

POST /groups

GET /users

GET /users/2

DELETE /users/2

POST /users

只是想对某个 只是想对某个 Group Group 中的 中的 Users Users 进行操作呢?进行操作呢?

map.resources :groups do |groups|

groups.resources :users

end

GET /groups/1/users

GET /groups/1/users/2

DELETE /groups/1/users/2

POST /groups/1/users

REST REST 世界中的 世界中的 Ajax Ajax 客户端客户端

• 通过 HTTP 来获取网络资源• 传输异步数据• 简单性• 可伸缩的架构

• 遵循 REST 架构“无状态服务器”的约束:– 服务器不关心客户端的状态– 客户端管理自己状态

RESTful Login & Search?RESTful Login & Search?

• 你如何实现 Login ?• POST /login?user=shaokun&password=***• POST /signin?user=shaokun&password=***

• https://reg.163.com/logins.jsp• http://ptlogin2.qq.com/login

• Login 的 Resource 是什么?• Login 的 HTTP Verb 是什么?• Login 的 Controller Action 是什么?

class SessionsController < ApplicationController # GET /sessions def new end

# POST /sessions def create end

# DELETE /sessions # logout def destroy endend

RESTful Search?RESTful Search?

• http://www.google.com/search?q=rest

• http://www.baidu.com/s?wd=rest

class SearchController < ApplicationController

# GET /search

def new

end

# POST /search

def create

end

end

• “ 天才”般简单地颠覆了 Google 和 Baidu ?• 但是……

– 构造了一个更复杂的操作– 无法简单的返回缓存结果– 无法复制搜索结果的 URL

• REST 错了吗?我们错了吗?

• http://www.google.com/search?q=REST– HTTP Verb 是 GET– scope 是 “ /search?q=REST”

• http://www.google.com/search?q=ruby– scope 是 “ /search?q=ruby”

• http://www.google.com/– scope 是 “ /”

Twitter & Facebook APITwitter & Facebook API

Twitter APITwitter API

• 基于 Ruby on Rails

• 比较遵循 REST 架构

• 支持多用响应格式,例如 xml , json , rss , atom 等

• 简单学、简单用

• 浏览器中– http://twitter.com/statuses/user_timeline/kudelabs.xml

• 命令行中– curl -X GET http://twitter.com/statuses/public_timeline– curl –X GET http://twitter.com/statuses/user_timeline/kudelabs.xml

– curl 更新 Kude Labs 的 Twitter

<statuses type="array"> <status> <created_at>Wed Feb 25 07:45:57 +0000 2009</created_at> <id>1248444034</id> <text>What to eat tonight?</text> <source>web</source> <truncated>false</truncated> <in_reply_to_status_id/> <in_reply_to_user_id/> <favorited>false</favorited> <in_reply_to_screen_name/> </status></statuses>

操作操作 HTTP VerbHTTP Verb URLURL

获取所有用户的 Statuses

GET http://twitter.com/statuses/public_timeline

获取特定用户的 Statuses

GET http://twitter.com/statues/user_timeline/userid.format

获取特定用户的某一个 Status

GET http://twitter.com/statues/show/statusid.format

创建一个新的 Status

POST http://twitter.com/statuses/update.format

删除一个 StatusDELETE/

POSThttp://twitter.com/statuses/destroy/statusid.format

GET /users/kudelabs/statuses.xmlGET /users/kudelabs/statuses.xml

GET /statuses/user_timeline/kudelabs.xmlGET /statuses/user_timeline/kudelabs.xml

完全的 完全的 RESTful Twitter APIRESTful Twitter API

操作操作 HTTP VerbHTTP Verb URLURL

获取所有用户的 Statuses GET /statuses.format

获取特定用户的 Statuses GET /users/{user_id}/statuses.format

获取特定用户的某一个 Status GET /users/{user_id}/statues/{status_id}.format

创建一个新的 Status POST /users/{user_id}/statuses.format

更新一个 Status PUT /users/{user_id}/statuses/{status_id}.format

删除一个 Status DELETE /users/{user_id}/statuses/{status_id}.format

Facebook APIFacebook API

• Facebook 是怎么描述它的 API 的:

– The API uses a REST-like interface.

– This means that our Facebook method calls are made over the internet by sending HTTP GET or POST requests to the Facebook API REST server (http://api.facebook.com/restserver.php).

– Nearly any computer language can be used to communicate over HTTP with the REST server.

RESTful API?RESTful API?

• Users.getInfo

• Parameters:– Required

• api_key, call_id, sig, v, uids, fields

– Optional• session_key, format, callback

• Error Codes:– 1, 2, 5, 100, 101, 102, 103, 104, 601

只是一种 只是一种 RPC APIRPC API

• 唯一的入口http://api.facebook.com/restserver.php

• 严重依赖于 POST• 调用方法隐藏于参数中,例如 Users.getInfo• 自定义的、非 HTTP 的响应码

• 支持多种响应

T i p sT i p s

• 对新技术趋之若鹜

• 我创建的、愚蠢的 Resource:– Ownership– Membership– Nomination– Authorization

RESTful too MUCHRESTful too MUCH

User A 创建 Bookmark A

# POST /bookmarks

User X 评论 Bookmark A

# POST /bookmarks/1/comments

User A 将某一个评论标为 Spam

# PUT /bookmarks/1/comments/2/mark_spam

mark_spammark_spam

并不是一个标准的 并不是一个标准的 ActionAction并不遵循 并不遵循 REST REST 架构架构

I am creating a SPAM resource!I am creating a SPAM resource!

POST /bookmarks/1/comments/2/spamPOST /bookmarks/1/comments/2/spam

map.resources map.resources :users:users do |users| do |users|

users.resources users.resources :bookmarks:bookmarks do |bookmarks| do |bookmarks|

bookmarks.resources bookmarks.resources :comments:comments do |comments| do |comments|

comments.resource comments.resource :spam:spam

endend

endend

endend

Your Your geniusgenius API for your team API for your team

GET /users/1/bookmarks/2/comments

GET /users/1/bookmarks/2/comments/3

POST /users/1/bookmarks/2/comments

POST /users/1/bookmarks/2/comments/3/spams

POST /users/1/bookmarks/2/comments/3/spamsPOST /users/1/bookmarks/2/comments/3/spams

POST /comments/3/mark_spamPOST /comments/3/mark_spam

• 是否容易被团队成员接受?• Accept by your team

• 是否存在于团队常用用例中的词汇?• Common vocabulary

• 是否有助于将其开放为 API ?• Help expose as a API

• 是否为开发人员建立更简单的、可遵循的规则?• Simple rules, could be followed by your team

• 与现存的、有用的插件是否兼容?• Work with the existing great plugin

POST /restserver.php?method=Users.getInfo&POST /restserver.php?method=Users.getInfo& format=xml& format=xml& id=398382 id=398382

GET /users/398382.xmlGET /users/398382.xml

如果你还有兴趣……如果你还有兴趣……

http://media.rubyonrails.org/presentations/worldofresources.pdf

O’REILLY 出版的 RESTful Web Services

git clone http://github.com/shaokun/restgit clone http://github.com/shaokun/rest

或者来 或者来 Kude Labs Kude Labs 做客做客

Q & AQ & Ashaokun@kudelabs.comshaokun@kudelabs.com