如何使用带有参数的Rails命名路由助手?

Ant*_*Ant 28 routes ruby-on-rails

鉴于这条路线

match 'posts/hello/:name/:title' => 'post#show', :as => :hello
Run Code Online (Sandbox Code Playgroud)
  • 我可以打电话的方式是hello_path什么?

  • 如果我打电话hello_path(@post),它会尝试做什么?

我希望:name和:title文件将自动绑定到路径,但似乎rails只知道如何从模型对象中获取:id.

相反,它只有在我称之为的情况下才有效

<%= link_to "link2", hello_url(:name=> @post.name, :title=>@post.title) %>
Run Code Online (Sandbox Code Playgroud)

(缺乏适当的文件真的让我伤心)

Gre*_*egT 19

回答你的两个问题:

  • 在命令行中,运行rake routes以查看应用程序中的路由.它将向您显示可以使用命名路径的所有方法,只需将"_path"或"_url"添加到左侧显示的路径名称中.
  • 调用hello_path(@post)将生成该实例的显示页面的URL hello.

您调用它的方式是常态:

<%= link_to "link2", hello_url(:name=> @post.name, :title=>@post.title) %>
Run Code Online (Sandbox Code Playgroud)

但是,这也可能有效:

<%= link_to "link2", hello_url(@post.name, @post.title) %>
Run Code Online (Sandbox Code Playgroud)

这里有一些应该有用的文档(除了Rails API之外). http://guides.rubyonrails.org/routing.html

  • 感谢您的回答@GregT,但我认为这个问题“如果我调用 `hello_path(@post)`,它会尝试做什么?” 实际上是在问“路径助手不应该尝试调用帖子上的名称和标题,并正确填充路径吗?(例如,如果 post.name 是 'bam' 并且 post.title 是 'kapow',那么不应该使用 `hello_path (@post)` return 'posts/hello/bam/kapow'?如果不是,它实际上想做什么?)”我目前也在寻找这个问题的答案。如果您有任何见解,那就太棒了。 (2认同)

dec*_*lan 14

回答你的问题" hello_path尝试做什么?"

hello_path知道应该得到多少参数.这是通过计算命名参数来计算的config/routes.它将接受散列或参数列表.如果给它一个哈希值,则键必须与URL参数的名称匹配.如果你给它一个参数列表,它只是按位置匹配它们 - 第一个参数和第一个命名参数.

然后,它会调用to_param在每个单独加入他们一起(参数之前看到这里的代码,4.0分支).

如果你在期望2个或更多的参数时传入一个对象,它甚至不会在对象上调用to_param.那就是当你得到没有堆栈跟踪的错误时会说出类似的错误
No route matches {:controller=>"posts", :action=>"show", :id=>#<Post ...>}

使用1个命名参数

如果你只有一个命名参数,那么事情就非常简单了.如果您需要按名称而不是ID查找帖子,则可以重新定义to_param

class Post < ActiveRecord::Base
  ...
  def to_param
    name
  end
end
Run Code Online (Sandbox Code Playgroud)

使用多个命名参数

但是如果URL中有多个命名参数,那么重新定义to_param是不够的.假设你试过这个:

# app/models/post.rb
class Post < ActiveRecord::Base
  ...
  def to_param
    {name: name, title: title}
  end
end

# app/views/posts/index.html.erb
<%= post_path(post) %>
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您将收到路由错误,因为您没有向post_path传递足够的参数(参见上文).为了解决这个问题,我只是to_param明确地打电话:

 # app/views/posts/index.html.erb
 <%= post_path(post.to_param) %>
Run Code Online (Sandbox Code Playgroud)

这比大多数Rails路由魔法更不光滑,但效果非常好.如果您以后改变了查找帖子的方式,您所要做的就是重新定义to_param.不用担心你打过的所有地方post_path

在引擎盖下

要查看的相关代码是actionpack/lib/action_dispatch/routing


Jam*_*mes 6

你也可以这样称呼它

hello_path(@post.name, @post.title)
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你。


IAm*_*NaN 5

其他答案(在撰写本文时)很好,但是您对GregT答案的回答表明对Rails缺乏了解,这很好-我们都曾去过。

具体来说,Rails背后的三个关键原则是:配置约定,模型-视图-控制器体系结构(MVC)和REST。在每本Rails入门书籍的开头都有东西。初学者通常认为他们可以使用代码跳到第一章,但是Rails与许多其他主题的不同之处在于第一章解释了重要的概念,而不仅仅是章节的介绍。因为Rails不是“代码”,所以它是“代码框架”。

“约定之上的配置”意味着如果您遵循某些约定,那么您将从受益于Rails的行为中受益。路由是即使不是最大的那些领域之一,尽管它是完全可配置的,但约定对开发人员有利。

遵循特定路由格式的路径将解析为控制器,操作以及可能的id,格式和其他参数。默认情况下,至少,Rails(以及Sinatra)路径采用以下格式和顺序:

/controller_name/action_name
Run Code Online (Sandbox Code Playgroud)

相比之下,它要复杂一些,具有更多选项,实际上它看起来像这样:

/controller_name/action_name/(id)(.format)(?param=value)(&...)
Run Code Online (Sandbox Code Playgroud)

...但是比这个答案所必需的更为详细。

该控制器是MVC中C,或类处理该请求。该动作是七个的RESTful动作(之一index,show,new,create,edit,update,和destroy该控制器内)。并非所有的操作都需要一个id( index,new和create),而不是所有的人都get请求(即产生一个视图,例如请求destroy,create并且update没有意见)。

放在一起,我们看到了这个例子:

/articles/edit/1
Run Code Online (Sandbox Code Playgroud)

…会将请求路由到带有ID 1 的ArticlesController控制器中的“ edit”操作。预计该控制器将进行一些内务处理,例如身份验证和授权,然后检索ID为1的Article模型(M CV)并传递然后转到“编辑”视图(MC V)。

最好,特别是对于新的Rails开发人员,要遵循这些约定,并可能在REST提供的行为之外添加一些其他行为。

您可以通过在routes.rb文件中配置其他路由方案(而不是遵循REST等)来超出此约定,但是您就像是一条鲑鱼在上游游动,这比顺其自然要难得多。如果您走这条路(双关语),您将自己做很多额外的工作,可能会稍作重新发明,并失去Rails框架提供的优势。如果您出于某种原因而处于这种情况,也许Rails并不是您工作的正确工具。

  • 我不会对此表述不一,因为它表达得很清楚,但是:它无助于解决发布者的问题,并且B,任何运行Rails的企业体系结构都将很快变成一项功能,它所需要的不仅仅是框架提供的约定。 。Rails确实存在漏洞以破坏REST。它可能被滥用,您对鲑鱼类比是正确的。我只是认为您的答复对于一般行业使用而言过于理想化。 (3认同)