如何使用Rails命名路由助手与参数?
鉴于这条路线
match 'posts/hello/:name/:title' => 'post#show', :as => :hello
-
我可以调用
hello_path
的方式是什么? -
如果我调用
hello_path(@post)
,它会尝试做什么?
我希望:name
和:title
文件会自动绑定到路径,但似乎rails只知道如何从模型对象中获取:id。
相反,它只有在我称之为的情况下才有效
@post.name, :title=>@post.title) %>
(缺乏适当的文件真的让我伤心)
回答你的两个问题:
- 在命令行中,运行
rake routes
以查看应用程序中的路由。 它将向您显示可以使用命名路径的所有方法,只需将“_path”或“_url”添加到左侧显示的路径名称中。 - 调用
hello_path(@post)
将生成该hello
实例的show页面的URL。
您调用它的方式是常态:
<%= link_to "link2", hello_url(:name=> @post.name, :title=>@post.title) %>
但是,这也可能有效:
<%= link_to "link2", hello_url(@post.name, @post.title) %>
这里有一些应该有用的文档(除了Rails API之外)。 http://guides.rubyonrails.org/routing.html
回答你的问题“ hello_path
尝试做什么?”
hello_path
知道它应该获得多少参数。 这是通过计算config/routes
的命名参数来计算的。 它将接受散列或参数列表。 如果给它一个哈希值,则键必须与URL参数的名称匹配。 如果给它一个参数列表,它只是按位置匹配它们 – 第一个参数与第一个命名参数匹配。
然后,它会在将每个参数连接在一起之前单独调用每个参数的to_param
( 参见此处的代码,4.0分支 )。
如果你在期望2个或更多参数时传入一个对象,它甚至不会在对象上调用to_param。 那就是当你得到没有堆栈跟踪的错误时会说出类似的错误
No route matches {:controller=>"posts", :action=>"show", :id=>#
使用1个命名参数
如果你只有一个命名参数,那么事情就非常简单了。 如果您需要按名称而不是ID查找post,则可以重新定义to_param
class Post < ActiveRecord::Base ... def to_param name end end
使用多个命名参数
但是如果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) %>
在这种情况下,您将收到路由错误,因为您没有向post_path传递足够的参数(参见上文)。 为了解决这个问题,我只需要明确地调用to_param
:
# app/views/posts/index.html.erb <%= post_path(post.to_param) %>
这比大多数Rails路由魔法更不光滑,但效果非常好。 如果你以后改变了查找post的方式,你所要做的就是重新定义to_param。 无需担心你称之为post_path
所有地方
在引擎盖下
要查看的相关代码是actionpack / lib / action_dispatch / routing
你也可以这样称呼它
hello_path(@post.name, @post.title)
希望能帮助到你。
其他答案(在撰写本文时)很好,但您对GregT答案的回复显示对Rails缺乏了解,这很好 – 我们都去过那里。
具体来说,Rails背后的三个关键原则: 约定优于配置 , 模型 – 视图 – 控制器架构 (MVC)和REST 。 这是每个Rails书开头的东西。 初学者通常认为他们可以通过代码跳到第一章,但是Rails与许多其他主题不同,因为第一章解释了重要的概念,而不仅仅是介绍章节的填充。 因为Rails不是“代码”,所以它是一个“代码框架”。
“约定优于配置”意味着如果您遵循某些约定,那么您将受益于Rails中的行为。 路由是其中一个领域,如果不是最大的领域,那么惯例会使开发人员受益,尽管它是完全可配置的。
遵循特定路由格式的路径将被解析为控制器,操作以及可能的id,格式和其他参数。 默认情况下,Rails(以及Sinatra)路径至少采用以下格式和顺序:
/controller_name/action_name
它有点复杂,有更多选项,实际上看起来更像这样:
/controller_name/action_name/(id)(.format)(?param=value)(&...)
……但这个问题比这个答案所需要的更详细。
控制器是MVC中的C,或处理请求的类。 该操作是该控制器中的七个RESTful操作之一( index
, show
, new
, create
, edit
, update
和destroy
)。 并非所有操作都需要id( index
, new
和create
),并且并非所有操作都是get
请求(生成视图的请求,例如destroy
, create
和update
没有视图)。
把它们放在一起我们看到这个例子:
/articles/edit/1
…将把请求路由到传递给身份1的ArticlesController控制器中的’edit’动作。预计控制器将执行一些内务管理,如身份validation和授权,然后检索ID为1的文章模型( M CV)并通过它沿着“编辑”视图(MC V )。
最好,特别是对于新的Rails开发人员,坚持这些约定,并且可能添加一些除REST提供的操作之外的其他操作。
你可以通过在routes.rb文件中配置一个替代的路由方案,而不是关注REST等来超越这个约定,但你会像上游游泳一样鲑鱼 – 它比流动更难。 如果你沿着这条路走(双关语),你将为自己做很多额外的工作,可能会在某种程度上重新发明轮子,并失去Rails框架提供的优势。 如果您因任何原因发现自己处于这种情况,也许Rails不适合您的工作。
- 带有Turbolinks的Googletagmanager
- Rails – 使用另一个类方法中的类方法和第二个类的一个属性
- rake / rails .save! 没有更新数据库
- 允许匿名/来宾用户“试用”function,而无需在Rails / Devise / CanCan应用程序中注册
- Rails:完全被delayed_job困扰。 在任何地方都没有收到
- Rails – 单表inheritance与否是申请人/员工关系
- public_id在cloudinary和carrierwave之间不匹配
- `method_missing’:用户的未定义方法`devise’(调用’User.connection’建立连接)
- rails设计edit_user_password_path