rails URL_FOR

url_for()方法通过将它的参数传递给一个映射来生成URL。在可以在“控制器”和“视图”中工作。让我们试试。

@link = url_for :controller => "store", :action => "display", :id => 123

这个代码将把@link设置成像这样

http://pragprog.com/store/display/123

url_for()方法接受我们的参数并映射它们到一个与我们自己的“路由器”兼容的请求中。如果用户选择了有些连接的URL,它将调用我们应用程序希望的动作。

经过重载后的url_for()会更聪明。它知道有关的缺省参数并生成你希望的最小限度的URL。让我们看一些例子。

# 没有 action 或者 id, 则重载版本使用缺省值。

url_for(:controller => "store")

#=> http://pragprog.com/store

# 如果action被丢失,则重载版本会在URL中插入缺省值—index。

url_for(:controller => "store", :id => 123)

#=> http://pragprog.com/store/index/123

# id 是可选的。

url_for(:controller => "store", :action => "list")

#=> http://pragprog.com/store/list

# 一个完整的请求。

url_for(:controller => "store", :action => "list", :id => 123)

#=> http://pragprog.com/store/list/123

# 额外的参数被添加到URL的尾部。

url_for(:controller => "store", :action => "list",:id => 123, :extra => "wibble")

#=> http://rubygarden.org/store/list/123?extra=wibble

缺省机制使用从当前请求获得的值。如果:controller参数被忽略的话,这是大多数填充当前“控制器”的名字的用法。假设下面例子在处理传递给store “控制器”的请求时运行。注意,它如何填充URL内的“控制器”名字。

url_for(:action => "status")

#=> http://pragprog.com/store/status

URL生成工作以可用于更复杂的“路由器”。例如,我们博客的“路由器”包含下面映射。

map.connect "blog/:year/:month/:day",

:controller => "blog",

:action => "show_date",

:requirements => { :year => /(19|20)dd/,

:month => /[01]?d/,

:day => /[0-3]?d/},

:day => nil, # optional

:month => nil # optional

map.connect "blog/show/:id",

:controller => "blog",

:action => "show",

:id => /d+/ # must be numeric

map.connect "blog/:controller/:action/:id"

假设引入请求是http://pragprog.com/blog/2005/4/15。这个请求会被第一个规则映射给Blog “控制器”的show_date动作。让我们看看在这些情况下,会产生什么样的url_for()调用。

如果我们为不同的天要求一个URL,映射调用将接受来自请求的值做缺省值,只是day参数改变了。

url_for(:day => "25")

#=> http://pragprog.com/blog/2005/4/25

现在让我们看看,如果我们给出年会发生什么情况。

url_for(:year => "2004")

#=> http://pragprog.com/blog/2004

太灵巧了。映射代码设想URL被表示成一个值的层次。[在web上这很正常,静态的内容被存储在文件夹(目录)内,它们本身也可以是文件夹,等等。]一旦我们在这个层次的一个级别上修改一些东西的缺省值,它会停止给较低级别提供缺省值。最合理的解释是:低层的参数事实上只能在高层中使用,所以修改的缺省值在低层中无效。在这个例子中通过覆写年,我们含蓄地告诉映射代码,我们不需要月和天。

也要注意映射代码会为提交的URL尽可能地选择第一条规则。让我们看看,如果我们给它不能由第一条规则—基于日期的规则,匹配的值,会发生什么事情。

url_for(:action => "edit", :id => 123)

#=> http://pragprog.com/blog/blog/edit/123

这儿,第一个blog是固定文本,第二个blog是“控制器”的名字,edit是“动作”名字—映射代码应用第三个规则。如果我们指定“动作”为show,则映射代码使用第二个规则。

url_for(:action => "show", :id => 123)

#=> http://pragprog.com/blog/show/123

大多数时候映射代码会完成你想要的工作。但是,它有时候也太聪明了。如果你想生成2005年的URL。你可以写

url_for(:year => "2005")

当你看到映射代码解释的URL也包含月和天时,你会大吃一惊。

#=> http://pragprog.com/blog/2005/4/15

你提供的年的值也同样被用在当前请求中。因为这个参数没有被修改,映射为URL的余下部分使用了月和天的缺省值。要避免这样,可设置月的参数为nil。

url_for(:year => "2005", :month => nil)

#=> http://pragprog.com/blog/2005

通常,如果你想生成一个特定的URL,最好的办法是设置未被使用的第一个参数为nil;这样做可避免使用URL留下的参数。

有时候你希望做相反的事情,修改层次中高层参数的值,并强迫“路由器”代码继续使用低层中的值。在我们例子中,这就像是在URL指定了一个不同的年,并在它的后面添加现有的月和日的缺省值。要做到这点,我们可以欺骗“路由器”代码—我们使用:overwrite_params选项来告诉它,原有请求的参数包含我们想使用的新的年。因为它认为年没有被修改,它继续使用余下的缺省值。

url_for(:year => "2002")

#=> http://pragprog.com/blog/2002

url_for(:overwrite_params => {:year => "2002"})

#=> http://pragprog.com/blog/2002/4/15

一个映射有个必须条件,如

map.connect "blog/:year/:month/:day",

:controller => "blog",

:action => "show_date",

:requirements => { :year => /(19|20)dd/,

:month => /[01]d/,

:day => /[0-3]d/},

注意:day参数必须匹配/[0-3]d/;它必须有两个数字长。这意味着当创建一个URL时,如果你传递的Fixnum值小于10,这个规则将不会起作用。

url_for(:year => 2005, :month => 12, :day => 8)

因为数字8被转换为字符串”8”,而那个字符没两个数字长,映射就不会被激活。可以是对relax规则(在请求中使用[0-3]?d来要求前导的零)进行修改,或者是确保你传递两个数字。

url_for(:year=>year,

:month=>sprintf("%02d", month),

:day=>sprintf("%02d", day))




“控制器”的命名


在182页我们说过,“控制器”应该被分组到模块中,并且引入的URL使用类似路径的约定来确定这些“控制器”。http://my.app/admin/book/edit/123的URL将调用Admin模块内Book“控制器”的edit“动作”。

这个映射也影响URL的生成。

1、如果你没有指定一个:controller参数给url_for(),它使用当前的“控制器”。

2、如果你传递一个以a/开头的“控制器”的名字,那么那个名字是绝对的。

3、所有其它的“控制器”名字则相对于请求的“控制器”的模块。

要说明这一点,让我们假设有个请求是

http://my.app/admin/book/edit/123

url_for(:action => "edit", :id => 123)

#=> http://my.app/admin/book/edit/123

url_for(:controller => "catalog", :action => "show", :id => 123)

#=> http://my.app/admin/catalog/show/123

url_for(:controller => "/store", :action => "purchase", :id => 123)

#=> http://my.app/store/purchase/123

url_for(:controller => "/archive/book", :action => "record", :id => 123)

#=> http://my.app/archive/book/record/123




-------------------------------------------------------------------

David 说. . .

Pretty URLs Muddle the Model

Rails 用它自己的方式为怎么让URL有个好名字而提供了足够的灵活性。事实上,它支持的足够深,以至于你可以混合你的“模型”类。“模型”与“视图”之间的这种交互似乎违背了MVC,但对我们却很有好处。

让我们假充你希望你的URL看起来这样:/clients/pragprog/agilweb,以便你使用 /clients/:client/:project做为“路由器”。你可以这样生成URL。

url_for :controller => "clients",

:client => @company.short_name,

:project => @project.code_name

这很好,但是它意味着我们要给一个公司生成一个URL组件,我们需要记住调用short_name(),并且每次我们都包括一个project在URL中,我们必须调用code_name()。

如果一个对象实现了方法to_param(),则方法的返回值将在向URL提供值是被使用(不是to_s())。通过在Company和Project两者中实现适当的to_param()方法,我们可以对连接的生成简化为

url_for :controller => "clients",

:client => @company,

:project => @project

Doesn’t that just make you feel all warm and fuzzy?

----------------------------------------------------------

现在我们已经看到映射是如何被用于生成URL的,我们可以全面地查看url_for()方法。

url_for 创建引用这个应用程序的一个URL。

url_for(option => value, ...)

在这个应用程序中创建个引用了一个“控制器”的URL。哈希表选项支持参数的名字和它们用于填充URL(基于一个映射)的值。参数值必须匹配任何由使用的映射强加的约束。在选项列表内的某些参数的名字:余下部分,被保留并且用于填充URL的非路径部分。如果你使用一个“活动记录”的“模型”对象做为url_for()(或者是任何相关的方法)内的一个参数,则那个对象的数据库id将会被使用。下面代码片断内的两个重定向调用有同样的效果。

user = User.find_by_name("dave thomas")

redirect_to(:action => 'delete', :id => user.id)

# can be written as

redirect_to(:action => 'delete', :id => user)

url_for( ) 也接受单个字符串或符号做为一个参数。这一般在Rails内部使用。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值