如何使用Rails命名路由助手与参数?

时间:2022-06-08 10:59:16

given this route

鉴于这条路线

match 'posts/hello/:name/:title' => 'post#show', :as => :hello
  • what are the ways that I can call hello_path ?

    我可以调用hello_path的方式是什么?

  • if i call hello_path(@post), what does it try to do?

    如果我调用hello_path(@post),它会尝试做什么?

I was hoping that the :name and :title files will bind to the path automatically but it seems that rails only know how to get the :id out of the model object.

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

instead, it only works if I call it like

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

<%= link_to "link2", hello_url(:name=> @post.name, :title=>@post.title) %>

(lack of proper documentation is really killing me)

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

4 个解决方案

#1


15  

To answer your two questions:

回答你的两个问题:

  • At the command line, runrake routes to see what routes there are in your app. It will show you all the ways you can use the named routes, just add "_path" or "_url" to the name of the route which is shown on the left.
  • 在命令行中,运行路线以查看应用中的路线。它将向您显示可以使用命名路径的所有方法,只需将“_path”或“_url”添加到左侧显示的路径名称中。
  • Calling hello_path(@post) will generate a URL to the show page for that hello instance.
  • 调用hello_path(@post)将生成该hello实例的show页面的URL。

The way you are calling it is the norm:

您调用它的方式是常态:

<%= link_to "link2", hello_url(:name=> @post.name, :title=>@post.title) %>

However, this may work too:

但是,这也可能有效:

<%= link_to "link2", hello_url(@post.name, @post.title) %>

Here is some documentation (other than the Rails API) which should help. http://guides.rubyonrails.org/routing.html

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

#2


12  

To answer your question of "what does hello_path try to do?"

hello_path knows how many parameters it's supposed to get. This is from counting the named parameters in config/routes. It will accept either a hash or a list of arguments. If you give it a hash, the keys must match the names of the URL parameters. If you give it a list of arguments, it'll just match them up by position - the first argument with the first named parameter.

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

Then, it will call to_param on each parameter individually before joining them all together (see code here, 4.0 branch).

然后,它会在将每个参数连接在一起之前单独调用每个参数的to_param(参见此处的代码,4.0分支)。

If you pass in an object when it's expecting 2 or more params, it won't even get around to calling to_param on the object. That's when you get errors with no stack trace that say something like
No route matches {:controller=>"posts", :action=>"show", :id=>#<Post ...>}

如果你在期望2个或更多参数时传入一个对象,它甚至不会在对象上调用to_param。那就是当你得到没有堆栈跟踪的错误时,说没有路由匹配{:controller =>“posts”,:action =>“show”,:id =># }

Working with 1 named parameter

If you've only got one named parameter, things are pretty straightforward. If you need to look up your posts by name instead of id, you can just redefine to_param

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

class Post < ActiveRecord::Base
  ...
  def to_param
    name
  end
end

Working with multiple named parameters

But if the URL has more than one named parameter in it, then redefining to_param isn't enough. Let's say you tried this:

但是如果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) %>

In this case, you'll get a routing error because you're not passing in enough arguments to post_path (see above). To get around this, I just call to_param explicitly:

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

 # app/views/posts/index.html.erb
 <%= post_path(post.to_param) %>

This is a little less slick than most Rails routing magic, but works perfectly well. If you later change the way you're looking up Posts, all you have to do is redefine to_param. No need to worry about all the places you've called post_path

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

Under the hood

The relevant code to look at is actionpack/lib/action_dispatch/routing

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

#3


4  

You can also call it like this

你也可以这样称呼它

hello_path(@post.name, @post.title)

Hope it helps.

希望能帮助到你。

#4


4  

The other answers (at the time of this writing) are fine, but your reply to GregT's answer shows a lack of understand about Rails, which is fine -- we've all been there.

其他答案(在撰写本文时)很好,但您对GregT答案的回复显示对Rails缺乏了解,这很好 - 我们都去过那里。

Specifically, three of the key principles behind Rails: convention over configuration, the model-view-controller architecture (MVC), and REST. It's stuff at the beginning of every beginning Rails book. Beginners often think they can just jump to the first chapter with code, but Rails differs from many other topics in that the first chapters explain important concepts and aren't just intro chapter filler. Because Rails isn't "code", it's a "framework of code".

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

"Convention over configuration" means if you follow certain conventions then you benefit from behaviors baked into Rails. Routing is one of those areas, if not the biggest, where convention benefits the developer although it is entirely configurable.

“约定优于配置”意味着如果您遵循某些约定,那么您将受益于Rails中的行为。路由是其中一个领域,如果不是最大的领域,那么惯例会使开发人员受益,尽管它是完全可配置的。

Paths following a specific routing format, are parsed into the controller, action and possibly an id, format, and additional parameters. By default and at minimum, a Rails (and also a Sinatra) path takes the following format and order:

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

/controller_name/action_name

It's a little more complicated than that, with more options, and it looks more like this in actuality:

它有点复杂,有更多选项,实际上看起来更像这样:

/controller_name/action_name/(id)(.format)(?param=value)(&...)

...but it's more detail than is necessary for this answer.

......但这个问题比这个答案所需要的更详细。

The controller is the C in MVC, or the class that handles the request. The action is one of the seven RESTful actions (index, show, new, create, edit, update, and destroy) within that controller. Not all actions require an id (index, new and create) and not all of them are get requests (requests that generate a view, for instance destroy, create and update don't have views).

控制器是MVC中的C,或处理请求的类。该操作是该控制器中的七个RESTful操作之一(索引,显示,新建,创建,编辑,更新和销毁)。并非所有操作都需要id(index,new和create),并且并非所有操作都是get请求(生成视图的请求,例如destroy,create和update没有视图)。

Putting it all together we see this example:

把它们放在一起我们看到这个例子:

/articles/edit/1

...will route the request to the 'edit' action in the ArticlesController controller passing along id 1. It's expected that the controller will do some housekeeping, like authentication and authorization, then retrieve Article model (MCV) with ID 1 and pass it along to the "edit" view (MCV).

...将把请求路由到传递给身份1的ArticlesController控制器中的'edit'动作。预计控制器将执行一些内务管理,如身份验证和授权,然后检索ID为1的文章模型(MCV)并传递它沿着“编辑”视图(MCV)。

It's best, especially for new Rails developers, to stick to these conventions and perhaps add a few additional actions beyond those provided by REST.

最好,特别是对于新的Rails开发人员,坚持这些约定,并且可能添加一些除REST提供的操作之外的其他操作。

You can step outside this convention by configuring in your routes.rb file an alternative routing scheme, not following REST, etc., but you'll be like a salmon swimming upstream -- it's a lot harder than going with the flow. If you go down that path (pun) you'll make a lot of additional work for yourself, probably reinvent the wheel somewhat, and lose advantages provided by the Rails framework. If you find yourself in that situation for whatever reason, perhaps Rails isn't the right tool for your job.

你可以通过在routes.rb文件中配置一个替代的路由方案,而不是关注REST等来超越这个约定,但你会像上游游泳一样鲑鱼 - 它比流动更难。如果你沿着这条路走(双关语),你将为自己做很多额外的工作,可能会在某种程度上重新发明*,并失去Rails框架提供的优势。如果您因任何原因发现自己处于这种情况,也许Rails不适合您的工作。

#1


15  

To answer your two questions:

回答你的两个问题:

  • At the command line, runrake routes to see what routes there are in your app. It will show you all the ways you can use the named routes, just add "_path" or "_url" to the name of the route which is shown on the left.
  • 在命令行中,运行路线以查看应用中的路线。它将向您显示可以使用命名路径的所有方法,只需将“_path”或“_url”添加到左侧显示的路径名称中。
  • Calling hello_path(@post) will generate a URL to the show page for that hello instance.
  • 调用hello_path(@post)将生成该hello实例的show页面的URL。

The way you are calling it is the norm:

您调用它的方式是常态:

<%= link_to "link2", hello_url(:name=> @post.name, :title=>@post.title) %>

However, this may work too:

但是,这也可能有效:

<%= link_to "link2", hello_url(@post.name, @post.title) %>

Here is some documentation (other than the Rails API) which should help. http://guides.rubyonrails.org/routing.html

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

#2


12  

To answer your question of "what does hello_path try to do?"

hello_path knows how many parameters it's supposed to get. This is from counting the named parameters in config/routes. It will accept either a hash or a list of arguments. If you give it a hash, the keys must match the names of the URL parameters. If you give it a list of arguments, it'll just match them up by position - the first argument with the first named parameter.

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

Then, it will call to_param on each parameter individually before joining them all together (see code here, 4.0 branch).

然后,它会在将每个参数连接在一起之前单独调用每个参数的to_param(参见此处的代码,4.0分支)。

If you pass in an object when it's expecting 2 or more params, it won't even get around to calling to_param on the object. That's when you get errors with no stack trace that say something like
No route matches {:controller=>"posts", :action=>"show", :id=>#<Post ...>}

如果你在期望2个或更多参数时传入一个对象,它甚至不会在对象上调用to_param。那就是当你得到没有堆栈跟踪的错误时,说没有路由匹配{:controller =>“posts”,:action =>“show”,:id =># }

Working with 1 named parameter

If you've only got one named parameter, things are pretty straightforward. If you need to look up your posts by name instead of id, you can just redefine to_param

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

class Post < ActiveRecord::Base
  ...
  def to_param
    name
  end
end

Working with multiple named parameters

But if the URL has more than one named parameter in it, then redefining to_param isn't enough. Let's say you tried this:

但是如果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) %>

In this case, you'll get a routing error because you're not passing in enough arguments to post_path (see above). To get around this, I just call to_param explicitly:

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

 # app/views/posts/index.html.erb
 <%= post_path(post.to_param) %>

This is a little less slick than most Rails routing magic, but works perfectly well. If you later change the way you're looking up Posts, all you have to do is redefine to_param. No need to worry about all the places you've called post_path

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

Under the hood

The relevant code to look at is actionpack/lib/action_dispatch/routing

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

#3


4  

You can also call it like this

你也可以这样称呼它

hello_path(@post.name, @post.title)

Hope it helps.

希望能帮助到你。

#4


4  

The other answers (at the time of this writing) are fine, but your reply to GregT's answer shows a lack of understand about Rails, which is fine -- we've all been there.

其他答案(在撰写本文时)很好,但您对GregT答案的回复显示对Rails缺乏了解,这很好 - 我们都去过那里。

Specifically, three of the key principles behind Rails: convention over configuration, the model-view-controller architecture (MVC), and REST. It's stuff at the beginning of every beginning Rails book. Beginners often think they can just jump to the first chapter with code, but Rails differs from many other topics in that the first chapters explain important concepts and aren't just intro chapter filler. Because Rails isn't "code", it's a "framework of code".

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

"Convention over configuration" means if you follow certain conventions then you benefit from behaviors baked into Rails. Routing is one of those areas, if not the biggest, where convention benefits the developer although it is entirely configurable.

“约定优于配置”意味着如果您遵循某些约定,那么您将受益于Rails中的行为。路由是其中一个领域,如果不是最大的领域,那么惯例会使开发人员受益,尽管它是完全可配置的。

Paths following a specific routing format, are parsed into the controller, action and possibly an id, format, and additional parameters. By default and at minimum, a Rails (and also a Sinatra) path takes the following format and order:

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

/controller_name/action_name

It's a little more complicated than that, with more options, and it looks more like this in actuality:

它有点复杂,有更多选项,实际上看起来更像这样:

/controller_name/action_name/(id)(.format)(?param=value)(&...)

...but it's more detail than is necessary for this answer.

......但这个问题比这个答案所需要的更详细。

The controller is the C in MVC, or the class that handles the request. The action is one of the seven RESTful actions (index, show, new, create, edit, update, and destroy) within that controller. Not all actions require an id (index, new and create) and not all of them are get requests (requests that generate a view, for instance destroy, create and update don't have views).

控制器是MVC中的C,或处理请求的类。该操作是该控制器中的七个RESTful操作之一(索引,显示,新建,创建,编辑,更新和销毁)。并非所有操作都需要id(index,new和create),并且并非所有操作都是get请求(生成视图的请求,例如destroy,create和update没有视图)。

Putting it all together we see this example:

把它们放在一起我们看到这个例子:

/articles/edit/1

...will route the request to the 'edit' action in the ArticlesController controller passing along id 1. It's expected that the controller will do some housekeeping, like authentication and authorization, then retrieve Article model (MCV) with ID 1 and pass it along to the "edit" view (MCV).

...将把请求路由到传递给身份1的ArticlesController控制器中的'edit'动作。预计控制器将执行一些内务管理,如身份验证和授权,然后检索ID为1的文章模型(MCV)并传递它沿着“编辑”视图(MCV)。

It's best, especially for new Rails developers, to stick to these conventions and perhaps add a few additional actions beyond those provided by REST.

最好,特别是对于新的Rails开发人员,坚持这些约定,并且可能添加一些除REST提供的操作之外的其他操作。

You can step outside this convention by configuring in your routes.rb file an alternative routing scheme, not following REST, etc., but you'll be like a salmon swimming upstream -- it's a lot harder than going with the flow. If you go down that path (pun) you'll make a lot of additional work for yourself, probably reinvent the wheel somewhat, and lose advantages provided by the Rails framework. If you find yourself in that situation for whatever reason, perhaps Rails isn't the right tool for your job.

你可以通过在routes.rb文件中配置一个替代的路由方案,而不是关注REST等来超越这个约定,但你会像上游游泳一样鲑鱼 - 它比流动更难。如果你沿着这条路走(双关语),你将为自己做很多额外的工作,可能会在某种程度上重新发明*,并失去Rails框架提供的优势。如果您因任何原因发现自己处于这种情况,也许Rails不适合您的工作。