转载一篇比较详细介绍rails routes的文章

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”

本文出自 “{ :Alex Space => ” Ruby Notes ” }” 博客,请务必保留此出处http://blackanger.blog.51cto.com/140924/122055

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值