嵌套form_for的Rails路由错误 [英] Rails Routing Error for nested form_for
问题描述
我现在已经被问了一千遍了,但这对我没有帮助。:)我去过一个小时。我的表单:
I now this has been asked a thousand times but that doesn't help me heh :) I've been at this an hour. My form:
= form_for @comment, :url_for => { :action => "create", :controller => "comments"}, :method => :post
我的耙路:
POST /t/:trunk_id/r/:root_id/comments(.:format) {:action=>"create", :controller=>"comments"}
trunk_root_comment GET /t/:trunk_id/r/:root_id/comments/:id(.:format) {:action=>"show", :controller=>"comments"}
错误:
undefined method `comments_path' for #<#<Class:0x007fed2c713128>:0x007fed2c71cc78>
如果我将表格命名为:
= form_for [:trunk_root, @comment], :url_for => { :action => "create", :controller => "comments"}, :method => :post do |f|
这应该使路线trunk_root_comments_path ..根据耙路正确。
which should make the route trunk_root_comments_path.. which is correct according to the rake routes.. I get:
No route matches {:controller=>"comments", :format=>nil}
非常感谢帮助。.几个小时都在看这个。.
Help is very much appreciated.. been looking at this for hours..
更新:
谢谢瑞安这么好的回答!对于我当时只是在扔东西的事情,有一个非常明确的解释,至少我现在了解得更多。实际上,我的耙路中已经有 trunk_root_comments_path可用,并且我尝试了您提到的几种组合,但我并没有真正感到震惊,因此您提供了帮助。我正在使用Mongo,但实际上没有Trunk模型,我只有一个名为@ root.trunk的根属性,尽管我有一个Trunk控制器,因此它是我的路由的一部分(可能是个不好的主意idk) 。
Thank you Ryan for such a great answer! A very clear explanation of something I was just sort of 'throwing things' at, now at least I understand better. I actually already had 'trunk_root_comments_path' available in my rake routes, and I had tried a couple of the combinations you mentioned, but I wasn't really grocking what I was missing, so you helped. I'm using Mongo and I don't actually have a Trunk model, I just have an attribute on roots called @root.trunk, though I have a trunk controller and therefore its a part of my routes(maybe a bad idea idk).
所以我尝试了您的TLDR并显示错误:
So I tried your TLDR and it said error:
Undefined method 'root_comments_path'
..原因不存在Trunk模型,我想是?..所以我将@ trunk等于正确的ID,与
.. cause no Trunk model exists, I assume?.. so I made @trunk just equal the correct id with
= form_for [@trunk, @root, @comment] do |f|
<--我得到了'undefined method`politics_root_comments_path'..我很清楚..可能是有道理的..因为我失败了,所以我还必须尝试最明确的版本:
<- and I got 'undefined method `politics_root_comments_path''.. I figured well.. that probably makes sense.. since I'm failing I must as well try your most explicit version:
= form_for @comment, :url => (trunk_root_comments_path(:trunk_id => @root.trunk, :root_id => @root.id)) do |f|
肯定能奏效...所以我不太确定该怎么做这对我来说奇怪的是,我在路线中具有相同深度的嵌套资源照片,并且我能够使用= form_for [:trunk_root,@photo],:html => {:class =>'root_form'}做| f | ..但出于某种原因我不能..无论如何,我会说您给了我足够的知识以理解100%,但我认为我从20%的理解变成了50 %的理解..我现在知道ID对路由很重要,命名的助手需要访问它们。我对url_helper的工作方式进行了介绍,但是我需要进一步阅读以真正完善它。现在,我也能够以更长的形式构造适当的路线,至少可以度过这种棘手的情况。因此,谢谢您:)
and sure enough that worked... so I'm not quite sure how to do it shorter then this.. the odd thing for me is I have another nested resource "photos" at the same level of depth in the routes and I was able to get that to work with = form_for [:trunk_root, @photo], :html => { :class => 'root_form' } do |f|.. but here for some reason I couldn't.. anyways I'd say you gave me enough to understand 100% but I think I went from 20% understanding to 50% understanding.. I know now that id's ARE important to routes, and the named helpers need access to them. I got an introduction to how the url_helper works, but would need to read more on it to really grock it fully I think. I'm also now able to construct proper routes in their longer form at least to get through tricky situations like this. So thank you :)
推荐答案
TL; DR您需要同时指定:trunk_id
和您URL中的 root_id
或使用 form_for
这样:
TL;DR You need to specify both a :trunk_id
and a root_id
in your URL or use form_for
like this:
<%= form_for [@trunk, @root, @comment] do |f| %>
Rails试图从您提供的哈希值中构建URL,但该哈希值不会t匹配其路由表中的任何内容。您可以这样做:
Rails is attempting to build a URL from the hash you're giving it, but that hash doesn't match anything in its routing table. You could do this:
{ :controller => "comments", :action => "create", :trunk_id => trunk.id, :root_id => root.id }
但这确实有点 tl; dr 。
更酷的方法是:
trunk_root_comments_path(trunk, root)
其中 trunk
和 root
分别是 Trunk
和 Root
实例。
现在,如果您想成为超级邪恶的酷,请像这样:
Now, if you want to be super-wicked-cool, do it like this:
<%= form_for [trunk, root, comment] do |f| %>
科学!
所以这是如何运作的?小学,亲爱的:
Rails首先认识到我们正在使用 form_for
使用数组, 我们的意思是生意。 Rails使用传入的此数组并从中构建URL。它通过使用路由定义的路由帮助器来完成此任务。不幸的是,您已经以一种有趣的方式定义了您的路线,但效果并不理想,但是不要害怕!我们可以解决这个问题。
Rails first recognises that we're using form_for
using an Array and that we mean business. Rails uses this array passed in and builds a URL out of it. It does this by using the routing helpers that are defined by the routes. Unfortunately, you've defined your routes in a funny way that don't play nice with this, but don't fear! We can fix this.
您可以在 config / routes.rb
中找到它:
post '/t/:trunk_id/r/:root_id/comments'
而不是这样:
post '/t/:trunk_id/r/:root_id/comments', :as => "trunk_root_comments"
您可能已经 已经拥有了:
You may alternatively already have this:
match '/t/:trunk_id/r/:root_id/comments', :via => :post
应该成为哪个:
match '/t/:trunk_id/r/:root_id/comments', :via => :post, :as => "trunk_root_comments"
无论哪种方式,您现在都不是一个,而是路线定义的两个(!!) 路径助手。它们分别是 trunk_root_comments_path
和 trunk_root_comments_url
。 这些方法的名称对于我将要向您解释的内容非常重要。请注意!
Either way, you've now got not one, but two(!!) path helpers defined by the routes. These aretrunk_root_comments_path
and trunk_root_comments_url
respectively. The names of these methods are super important for what I am about to explain to you. Pay attention!
所以,回到我们的 form_for
小呼叫:
So, back to our little form_for
call:
<%= form_for [trunk, root, comment] do |f| %>
Rails知道我们正在使用数组,因为它可以看到它。这个数组的作用可能像魔术一样似乎,但并非如此。
Rails knows that we're using an Array because it can see it. What it does with this Array may seem like magic, but isn't really.
Rails将获取此数组的每个元素,并从不同部分构建一个路由辅助方法 name 。这实际上不是 form_for
的一部分,但可以单独使用另一种称为 url_for
的方法:
Rails will take each element of this array and build a routing helper method name up from the different parts. This isn't actually part of form_for
, but another method called url_for
that you can use by itself:
url_for([trunk, root, comment])
开头,由 url_for
生成的此路由帮助器方法名称只是一个空数组( []
)。没什么特别的。
In the beginning, this routing helper method name generated by url_for
is simply an empty array ([]
). Nothing special at all.
但是然后发生的事情是特殊的!
第一个元素将是 Trunk
类的持久化实例。 持久是指将直接映射到数据库中的记录的对象。是的ORM!
The first element is going to be a persisted instance of the Trunk
class. By "persisted" I mean that it's an object that maps directly to a record in the database. Yay ORMs!
Rails会知道这一点,因此会将路由助手转换为: [:trunk]
Rails will know this, and so will turn the routing helper into this: [:trunk]
.
第二个元素将是 Root
类的持久化实例 。 Rails也知道这一点(该死,Rails是 smart !),然后将其附加到数组中,将其转换为 [:trunk,:root]
。
The second element is going to be a persisted instance of the Root
class. Rails also knows this (damn, Rails is smart!) and will then append this to the array, turning it into [:trunk, :root]
. Awesome.
Rails然后检查第三个(也是最后一个)元素。它会发现(在这种情况下)它是一个非持久性元素,即尚未保存到数据库中。 Rails对此进行了不同的处理,而是将 [:comments]
追加到数组,并将其转换为:
The third (and final) element is then checked by Rails. It sees that (in this case) it's a non-persisted element, i.e. it's not been saved to the database.. yet. Rails treats this differently and will instead append [:comments]
to the array, turning it into this:
[:trunk, :root, :comments]
看看我在哪里
现在,Rails已经完成了它的工作(或者, thang ,如果您愿意的话),它将加入这三个部分像这样: trunk_root_comments
,并且为了很好的衡量,它会在其末尾放置 _path
并将其翻转进入最终的 trunk_root_comments_path
助手。
Now that Rails has done it's thing (or thang, if you like) it will join these three parts together like this: trunk_root_comments
, and just for good measure it'll put _path
on the end of it, turning it into the final trunk_root_comments_path
helper.
然后!伙计,然后... Rails调用此方法并传递参数!就像这样:
And then! Man, and then... Rails calls this method and passes it arguments! Just like this:
trunk_root_comments_path(:trunk_id => trunk.id, :root_id => root_id)
这将生成资源的完整路径,如下所示:
This generates a full path to the resource like this:
/t/:trunk_id/r/:root_id/comments
bam!整圈!这就是Rails知道如何生成URL的方式,您不必再使用丑陋的哈希值。
And bam! Full circle! That's how Rails will know to generate the URL and you don't have to use ugly hashes anymore.
成功!
这篇关于嵌套form_for的Rails路由错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!