1

I have a Profile model, which is inherited by a Customer and Vendor model. Profile has_many :posts.

When I do

form_for [ @profile, @post ] do |f|

Instead of callind profile_posts_path, form_for will actually call customer_posts_path or vendor_posts_path.

Since I want to have URLs like '/foo', '/bar', where foo and bar are usernames I wrote the routes like this:

resources :profiles, path: '/', constraints: { id: /[A-Z0-9\-\+\.]+/i } do
    resources :posts
end

resources :customers, path: '/', constraints: { id: /[A-Z0-9\-\+\.]+/i } do
    resources :posts
end

resources :vendors, path: '/', constraints: { id: /[A-Z0-9\-\+\.]+/i } do
    resources :posts
end

This way all requestes to '/foo' will be handled by the ProfilesController (it's the first in the list) and path helpers will be generated so that form_for will work.

However even if it works, this is far from ideal. There is evident repetition. If I need to add another nested resource I would have to add it trice.

So I refactored it like this (I know that this is horrible, but it works):

profile_block = Proc.new do
    resources :posts
end
resources :profiles, path: '/', constraints: { id: /[A-Z0-9\-\+\.]+/i }, &profile_block
resources :customer, path: '/', constraints: { id: /[A-Z0-9\-\+\.]+/i }, &profile_block
resources :vendor, path: '/', constraints: { id: /[A-Z0-9\-\+\.]+/i }, &profile_block

But this is still horrible. What I would really love to have is the as parameter to be an array, so that I could do:

resources :profiles, path: '/', constraints: { id: /[A-Z0-9\-\+\.]+/i }, as: [ 'profiles', 'customers', 'vendors' ] do
    ...
end

Is it possible to achieve something similar? Everything would be mapped to the same controller. And no repetition is in act. Any way to create named routes without having to call resources or match or anything...

Thanks in advance

edit: The relation between posts and profiles might become polymorphic in the near future. So the last solution proposed by AJcodex will break.

I find this frustrating, I will probably request this feature for the next rails

4

1 回答 1

1

一些选项:

  1. 使用符号form_for([:profile, @post]) do |f|

  2. 别名其他方法。请参阅此添加路由: 如何在 rails 3 中定义自己的路由助手?

    alias_method :customers_path, :profiles_path
    
  3. 遍历路由中的符号

在路线.rb

[ :profiles, :customers, :vendors ].each do |name|
  resources name, path: '/', constraints: { id: /[A-Z0-9\-\+\.]+/i }, as: name do
    resources :posts
  end
end

不过,您应该考虑使用客户端框架,因为这样您就可以将面向客户端的路由与 API 路由分开。与服务器的 RESTful 请求,用户的虚 URL。

编辑:

您是否有理由需要客户和供应商的帖子路线?让配置文件控制器处理所有帖子。一起摆脱供应商和客户喜欢的 url。

根据是客户还是供应商,如有必要,呈现不同的视图。

编辑2:

手工完成:

<%= form_for @post, as: :post, url: profile_path(@customer, @post) do |f| %>
  ...
<% end %>
于 2013-10-08T19:09:58.570 回答