kno*_*opx 27 routes ruby-on-rails nested-resources
正如我对嵌套资源的理解,边缘Rails,不应该
link_to 'User posts', @user.posts
Run Code Online (Sandbox Code Playgroud)
指向
/users/:id/posts
Run Code Online (Sandbox Code Playgroud)
?
routes.rb文件包含
map.resources :users, :has_many => :posts
Run Code Online (Sandbox Code Playgroud)
如果这不是默认行为,可以通过其他方式完成吗?
Rya*_*igg 54
和Rishav一样:
link_to "User Posts", [@user, :posts]
Run Code Online (Sandbox Code Playgroud)
这是我博客的解释.
真的很早就在Rails中,你会写这样的路线:
redirect_to :controller => "posts", :action => "show", :id => @post.id
Run Code Online (Sandbox Code Playgroud)
这将做的是尽职地重定向到show内部的动作,PostsController并传递id带有任何@post.id返回值的参数.典型的302响应.
然后Rails 1.2出现并允许您使用路由助手,如下所示:
redirect_to post_path(@post)
Run Code Online (Sandbox Code Playgroud)
人们欢欣鼓舞.
这将有效地做同样的事情.post_path这里将使用@post看起来类似的对象构建一个路由/posts/1,然后redirect_to向该路由发回302响应,浏览器将跟随它.
然后是更高版本(我不记得哪一个),允许这样的语法:
redirect_to @post
Run Code Online (Sandbox Code Playgroud)
人们第二次欢欣鼓舞.
任何足够先进的技术都与魔术无法区分.
虽然这看起来像魔术,但事实并非如此.这样做实际上非常非常整洁.该redirect_to方法与其表兄弟一样link_to,form_for都使用常用的方法来构建URL,称为url_for.该url_for方法采用许多不同种类的对象,例如字符串,哈希值甚至模型实例,如上例所示.
那么它对这些物体的作用非常简洁.在redirect_to @post上面的调用的情况下,它检查@post
对象,看到它是Post类的一个对象(我们假设,无论如何)并通过调用persisted?它来检查该对象是否已经存储在某个数据库中.
通过"持久化",我的意思是Ruby对象在某个地方的数据库中有匹配的记录.persisted?Active Record中的方法实现如下:
def persisted?
!(new_record? || destroyed?)
end
Run Code Online (Sandbox Code Playgroud)
如果对象不是通过调用创建的,Model.new那么它将不是新记录,如果它没有destroy调用该方法,它也不会被销毁.如果这两种情况都属实,那么这使得对象最有可能以记录的形式持久保存到数据库中.
如果它已被持久化,则url_for知道可以在某处找到此对象,并且可以找到它的位置很可能是在一个名为的方法下post_path.所以它调用这个方法,并传入to_param这个对象的值,通常是id.
简而言之,它有效地做到了这一点:
#{@post.class.downcase}_path(@post.to_param)
Run Code Online (Sandbox Code Playgroud)
这就是:
post_path(1)
Run Code Online (Sandbox Code Playgroud)
当调用该方法时,您将得到这个小字符串:
"/posts/1"
Run Code Online (Sandbox Code Playgroud)
可爱!
这称为多态路由.您可以将对象传递给类似的方法redirect_to,link_to并且form_for它将尝试计算出正确使用的URL.
现在,当你编写Rails代码时,form_for很久以前就可能已经使用过了这样的代码:
<% form_for @post, :url => { :controller => "posts", :action => "create" } do |f| %>
Run Code Online (Sandbox Code Playgroud)
当然,随着Rails的进步,你可以简化它:
<% form_for @post, :url => posts_path do |f| %>
Run Code Online (Sandbox Code Playgroud)
因为表单默认使用POSTHTTP方法,因此请求posts_path将转到
create操作PostsController,而不是index操作,如果它是GET请求将导致该操作.
但为何停在那里?为什么不写这个呢?
<%= form_for @post do |f| %>
Run Code Online (Sandbox Code Playgroud)
就个人而言,我认为没有理由不......如果它像这样简单.该form_for方法使用url_for底层,就像
redirect_to找出表单应该去的地方一样.它知道@post对象属于Post类(我们再次假设),它会检查对象是否持久化.如果是,那么它将使用post_path(@post).如果不是,那么posts_path.
该form_for方法本身检查传入的对象是否也是持久化的,如果是,那么它将默认为PUTHTTP方法,否则为POST.
所以这就是如何form_for灵活到在a new和editview 上都有相同的语法.如今,人们甚至将整个form_for标签整理成一个部分并将其包含在页面new和
edit页面中变得越来越普遍.
所以,form_for当你通过一个正常的对象相当简单,但如果你传递对象的数组,会发生什么?像这样,例如:
<%= form_for [@post, @comment] do |f| %>
Run Code Online (Sandbox Code Playgroud)
同时,双方url_for并form_for已为你披上也在那里.
该url_for方法检测到这是一个数组并分离出每个部分并单独检查它们.首先,这是什么
@post东西?那么,在这种情况下,我们假设它是Post该实例是持久和有1秒的ID,这是什么
@comment目的?这是一个Comment尚未持久保存到数据库的实例.
什么url_for会在这里做的是通过将每个部分在一个阵列,其连接到路由方法,然后调用所需的参数是路由方法建立由部分网址助手方法片.
首先,它知道@post对象属于Post类并且是持久化的,因此URL助手将以其开头post.其次,它知道该@comment对象属于Comment类并且不是持久化的,因此comments将遵循postURL帮助程序构建.url_for现在知道的部分是[:post, :comments].
该url_for方法将这些单独的部分与下划线组合在一起,以便它成为post_comments然后附加_path
到结尾,从而产生post_comments_path.然后它只将持久化对象传递给对该方法的调用,从而产生如下调用:
post_comments_path(@post)
Run Code Online (Sandbox Code Playgroud)
调用该方法会导致:
"/posts/1/comments"
Run Code Online (Sandbox Code Playgroud)
最好的部分?如果对象不是持久化对象,它form_for仍然会知道使用,如果是.要记住的一件好事是,始终是数组中指定的最后一个对象.它之前的对象只是它的嵌套,仅此而已.POST@commentPUTform_for
添加的对象越多,url_for执行硬码的次数就越多,并构建路径......虽然我建议您将其保留为两部分.
现在我们已经介绍了使用包含对象的数组form_for,让我们来看看另一个常见用法.包含至少一个Symbol对象的数组,如下所示:
<%= form_for [:admin, @post, @comment] do |f| %>
Run Code Online (Sandbox Code Playgroud)
这url_for方法的作用非常简单.它看到有一个Symbol并且照原样.url遗嘱的第一部分
与符号相同:admin.此时url_for知道的URL 就是[:admin].
然后url_for遍历数组的其余部分.在这种情况下,我们假设这两个@post和@comment的坚持,他们分别为1和2的ID.和以前一样的课程.url_for然后添加post到它正在构建的URL comment,结果也是如此[:admin, :post, :comment].
然后连接发生,导致一个方法admin_post_comment_path,因为这两个@post并且@comment在这里持久化,它们被传入,导致这个方法调用:
admin_post_comment_path(@post, @comment)
Run Code Online (Sandbox Code Playgroud)
哪(通常)变成这条路径:
/admin/posts/1/comments/2
Run Code Online (Sandbox Code Playgroud)
您可以使用多态路由的阵列形式redirect_to,link_to和form_for方法.可能还有其他我现在也不记得的方法也可以做到这一点......通常Rails中的任何方法通常都会使用URL.
没有必要使用哈希在任何大于2的Rails版本中构建您的URL; 那是一所非常古老的学校.
相反,尝试一下您对多态路由的新知识,并尽可能地利用它.
Ris*_*ogi 16
这应该工作:
link_to "User Posts", user_posts_path(@user)
更多详情,请访问:
http://guides.rubyonrails.org/routing.html
| 归档时间: |
|
| 查看次数: |
29671 次 |
| 最近记录: |