使用嵌套资源对一个多态资源进行DRY路由

时间:2012-03-08 11:47:35

标签: ruby-on-rails ruby-on-rails-3 routes actionpack

鉴于以下模型:

class Blog < ActiveRecord::Base
  has_many :posts
end

class SiteBlog < Blog
end

class ProjectBlog < Blog
end

class Post <ActiveRecord::Base
  belongs_to :blog
end

以下路线:

resources :blogs do
  resources :posts
end

在表单部分中,如果@blog是博客,则以下内容将正常工作:

form_for [@blog, @post] ...

但是,如果@blog是ProjectBlog或SiteBlog,它会爆炸,因为它将寻找一个URL帮助程序,例如project_blog_posts。

我想这样的事情可以解决这个问题:

[:project_blogs, :site_blogs].each |blogs| do
  resources blogs do
    resources :posts
  end
end

我想知道是否有办法使用子类模型(例如ProjectBlog)的路由来使用父模型(Blog)的路由。 “as”选项仅处理将[@blog,@ post]传递给form_for的 last 对象。

更新

根据以下要求,以下是路线:

resources :blogs, only: [:show] do
  resources :posts, only: [:new, :create, :edit, :update]
end

               blog_posts POST   /blogs/:blog_id/posts(.:format)                         posts#create
            new_blog_post GET    /blogs/:blog_id/posts/new(.:format)                     posts#new
           edit_blog_post GET    /blogs/:blog_id/posts/:id/edit(.:format)                posts#edit
                blog_post PUT    /blogs/:blog_id/posts/:id(.:format)                     posts#update
                     blog GET    /blogs/:id(.:format)                                    blogs#show

更新2:

以下答案提示:

form_for [@blog, @post], url: blog_posts_path(@blog, @post) do |f|

这仅适用于“新”操作,对于“编辑”操作,我会 - 正如预期的那样 - 得到一个错误的网址:

params[:action]   # => "edit"
blog_posts_path(@blog, @post)   # => "/blogs/publikationsreihe-tafelrunde/posts.5"

所以我提到的“if”会解决这个问题:

form_for [@blog, @post], url: params[:action]=='new' ? blog_posts_path(@blog, @post) : blog_post_path(@blog, @post) do |f|

但这看起来非常笨拙,必须有更好的方法。

1 个答案:

答案 0 :(得分:0)

通过将资源URL传递给表单,可以轻松解决:

<%= form_for [@blog, @post], :url => blog_posts_path(@blog, @post) do |f| %>
  ...
<%- end %>