首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网络技术 > 网络基础 >

rails restful 详细引见

2012-09-23 
rails restful 详细介绍原文:http://lcqcxxc.iteye.com/blog/1006270?REST, Resources, and Rails?Before

rails restful 详细介绍

原文:http://lcqcxxc.iteye.com/blog/1006270

?

REST, Resources, and Rails?

Before REST came I (and pretty much everyone else) never really knew where to?
put stuff.?
—Jonas Nicklas on the Ruby on Rails mailing list?

Routing and CRUD?
当你在routes.rb里这么写的时候:?
map.resources :auctions?
你就已经创造了4个具名路由,实际上允许你访问7个action(index, create, show,?
update, destroy, new, edit)。?

/auctions??? GET?

/auctions??? POST?

HTTP方法不同,尽管url相同,仍然还是两个不同的东西。来看一个RESTFul的路由表,显示了helpers,paths,以及controller action的关系:?
Helper????????????????????????????
client_url(@client)????????? -??? /clients/1 (show) ; /clients/1 (update); /clients/1 (destroy)?
clients_url????????????????????? -?? /clients (index) ; /clients (create)?
edit_client_url(@client)? -???? /clients/1/edit (edit)?
new_client_url?????????????? -???? /clients/new (new)?


当你生成一个URL的时候,你需要知道如何指定request方法,以防止你在GET /cients和POST /cients的时候触发了同一个action。看下面的一些规则:?

默认的request 方法是GET?
在form_for和form_tag方法被调用的时候,POST会被自动调用。?
你也能通过具名路由专门指定你需要的(几乎最多的是PUT 和 DELETE)。?
??? 例子:?
?? <%= link_to “Delete this auction”,:url => auction(@auction),:method => :delete %>?
?? 当调用update action的时候,需要指定PUT方法。?
??? <% form_for “auction”, :url => auction(@auction),:html => { :method => :put } do |f| %>?


The PUT and DELETE Cheat?
浏 览器通常不会支持GET, POST以外的HTTP方法,为了发送PUT,DELETE请求,Rails做了一些小技巧。 PUT, DELETE请求,在Rest in Rails的上下文中,实际上是带有一个隐藏域“_method”方法的POST, 这个隐藏域来设置是‘put’还是‘delete’。??

Singular and Plural RESTful Routes?
一些Restful路由是单数的,一些是复数的,规则如下:?
show,new, edit和destroy的路由是单数的,因为它们只为单独的资源工作。?
其余action的路由都是复数,因为它们要处理相关资源的集合。?
单数Restful路由需要一个参数,因为它需要指定你要操作资源的id:?
item_url(@item) # show, update, or destroy, depending on HTTP verb?
也可以用Hash的形式:?
item_url(:id => @item)?
你没必要一定要调用@item的id方法,Rails会帮你完成的。?

The Special Pairs: new/create and edit/update?
new / edit : 是用来得到form表单显示的。?
create/update:是用来处理form提交的数据的。?

new action,可以理解是得到一个单独的新的资源。但是HTTP动词GET,已经用在了show action上,所以new就必须有一个属于自己的名字。 这就是为什么我们需要这么使用:?
<%= link_to “Create a new item”, new_item_path %>?

edit action, 可以理解为给你一个不是正式的资源,是具有修改性质的的show资源,所以,这么用:?
edit_item_url(@item)?

Singular Resource Routes?
map.resources也有map.resource这样的单数形式。?
它一般被用在你应用上下文里仅出现一次的资源。看例子:?
假如有个地址簿的应用,可能给每一个登陆用户一个地址簿,所以你可以写:?
map.resource :address_book?
你就会得到:?
GET/PUT???? address_book_url,?
GET???????????? edit_address_book_url,?
PUT???????????? update_address_book_url.?

注意以上这个例子所有的具名路由都是单数的。它是假定这个通信录在对于一个用户是唯一的。这里没有任何魔术,你必须登陆并且从数据库查找属于那个用户的address book, 路由只是给你提供个方便罢了。?


Nested Resources?
拿书里的竞标例子来说,每一次投标(bid)都关联着同一个auction。这意味着:?
auction? has_many? bids?
就像这样的:/auctions/3/bids/5?
为什么不只是留下bids/5而跳过前面的auctions呢??
你可以从url上看出资源的信息。?
这种url可以让你使用params[:auctions_id]来访问auction的id。?

想创建嵌套资源,只需要在routes.rb里这么写:?
map.resources :auctions do |auction|?
?? auction.resources :bids?
end?

请注意里面的资源,是auction.? 而不是map.?
你可以使用,auction_bids_url, new_auction_bid_url等等。?
<%= link_to “See all bids”, auction_bids_path(@auction) %>?
这样你可以得到:/auctions/3/bids?
你能通过params[:auction_id]找到@auction的id。?

对于单独的bid资源(show,edit,destroy)你需要使用最少两个参数:?
<%= link_to “Delete this bid”,?
auction_bid_path(@auction, @bid), :method => :delete %>?

你也可以使用hash的形式,但是大部分人不喜欢长代码:?
auction_bid_path(:auction => @auction, :bid => @bid)?


Setting :path_prefix Explicitly?
设置前缀。?
map.resources :auctions?
map.resources :bids, :path_prefix => “auctions/:auction_id”?

这个前缀和上面的嵌套资源实现的结果一样。但是和嵌套资源比这种方式更常用。?

Setting :name_prefix Explicitly?
可以控制你路由生成helper的方式。比如:?
bid_path(@auction, @bid) 得到? /auctions/2/bids/5?
bid_path(@bid) 得到 /bids/5?

想实现这个功能,你只需要重写嵌套资源的name_prefix。?
map.resources :auctions do |auction|?
auction.resources :bids, :name_prefix => nil?
end?

你可能也想要这种helper方法:?
bid_path(@auction, @bid) # /auctions/1/bids/1?
bid_path(@person, @bid) # /people/1/bids/1?

map.resources :auctions do |auction|?
? auction.resources :bids, :name_prefix => nil?
end?
map.resource :people do |people|?
? people.resources :bids, :name_prefix => nil # are you sure??
end?


Specifying RESTful Controllers Explicitly?
资源和controller的对应,是根据命名约定自动映射的。比如:?
map.resources :auctions do |auction|?
? auction.resources :bids?
end?
对应的是AuctionsController和BidsController.你也可以自己指定controller:?
map.resources :my_auctions, :controller => :auctions do |auction|?
? auction.resources :my_bids, :controller => :bids?
end?

All Together Now?
现在我们知道了:name_prefix, :path_prefix, :controller三个选项。我们把它们一起来使用:?

map.resources :auctions do |auction|?
? auction.resources :bids, :name_prefix => nil,?
?????????????????????????? :controller => :auction_bids?
end?
map.resource :people do |people|?
? people.resources :bids, :name_prefix => nil,?
????????????????????????? :controller => :person_bids?
end?

AuctionBidsController和PersonBidsController会继承同一个父类BidsController。?

class BidsController < ApplicationController?
? before_filter :load_parent?
? before_filter :load_bid?

? protected?
? def load_parent?
??? # overriden in subclasses?
? end?

? def load_bid?
??? @bids = @parent.bids?
? end?
end?

class AuctionBidsController < BidsController?
? protected?
? def load_parent?
??? @parent = @auction = Auction.find(params[:auction_id])?
? end?
end?

class PersonBidsController < BidsController?
? protected?
? def load_parent?
??? @parent = @person = Person.find(params[:person_id])?
? end?
end?


Deep Nesting??

map.resources :auctions do |auctions|?
? auctions.resources :bids do |bids|?
??? bids.resources :comments?
? end?
end?
三层嵌套,这样可读性差。我们一般可以修改为:?
map.resources :auctions do |auctions|?
? auctions.resources :bids?
end?
map.resources :bids do |bids|?
? bids.resources :comments?
end?
map.resources :comments?

这样helper方法也容易去用:?
auctions_path # /auctions?
auctions_path(1) # /auctions/1?
auction_bids_path(1) # /auctions/1/bids?
bid_path(2) # /bids/2?
bid_comments_path(3) # /bids/3/comments?
comment_path(4) # /comments/4?

RESTful Route Customizations?
/auctions/3/bids/5/retract?

map.resources :auctions do |a|?
? a.resources :bids, :member => { :retract => :get }?
end?

<%= link_to “Retract”, retract_bid_path(auction, bid) %>?
也有:collection选项。?

Formatted Named Routes?
带格式的具名路由。?

<%= link_to “XML version of this auction”,formatted_auction_path(@auction, “xml”) %>?

会生成下列html:?
<a href=”/auctions/1.xml”>XML version of this auction</a>?


Reflecting on Rails Routing?

You are in a maze of twisty little passages, all alike.?
—Adventure (late 70s-era computer game)?

Examining Routes in the Application Console?
你可以在控制台检测你的路由系统。?

Dumping Routes?

$ ruby script/console?
Loading development environment.?
>> rs = ActionController::Routing::Routes?
>> puts rs.routes?

你可以看到全部定义好的路由:?
GET /bids/ {:controller=>”bids”, :action=>”index”}?
GET /bids.:format/ {:controller=>”bids”, :action=>”index”}?
… …?

Recognition and Generation in the Console?
$ ./script/console?
Loading development environment.?
>> irb ActionController::Routing::Routes?
>>?
irb这个命名,会在console里面生成一个默认的self对象,self是指ActionController::Routing::Routes这个的对象。?
你可以尝试以下命令:?

>> generate(:controller => “bids”, :auction_id => 3, :action =>?
“create”)?
=> “/auctions/3/bids”?

>> generate(:controller => “items”, :action => “item_year”, :year =>?
1939)?
=> “/item_year/1939”?
>> generate(:controller => “items”, :action => “item_year”, :year =>?
19393)?
=> “/items/item_year?year=19393”?
这个例子里year参数是4个数字,但是如果输入的不符合规范,则生成第二种url。?


>> recognize_path(“/”)?
=> {:controller=>”auctions”, :action=>”index”}?

>> recognize_path(“/auctions”, :method => :get)?
=> {:controller=>”auctions”, :action=>”index”}?

>> recognize_path(“/auctions”, :method => :post)?
=> {:controller=>”auctions”, :action=>”create”}?

>> recognize_path(“/auctions/3/bids”, :method => :post)?
=> {:controller=>”bids”, :action=>”create”, :auction_id=>”3”}?

>> recognize_path(“/users/3/bids/1/retract”, :method => :get)?
=> {:controller=>”bids”, :user_id=>”3”, :action=>”retract”, :id=>”1”}?

>>exit?
>>#<IRB::Irb: @context=#<IRB::Context:0×22f43f4>, @signal_status=:IN_EVAL, @scanner=#<RubyLex:0×22f3a6c>>?


Named Routes in the Console?
你也可以在控制台里执行命名路由。如下:?
>> include ActionController::UrlWriter?
=> Object?
>> default_url_options[:host] = “example.com”?
=> “example.com”?
>>?
>> auction_url(1)?
=> “http://example.com/auctions/1”?
>> formatted_auction_url(1,”xml”)?
=> “http://example.com/auctions/1.xml”?
>> formatted_auctions_url(“xml”)?
=> “http://example.com/auctions.xml”

热点排行