包装嵌套路由的命名路由助手

时间:2012-09-14 06:17:09

标签: ruby-on-rails ruby url-routing

所以我刚刚与一位同事走出了激烈的宗教争论。

我们有对象模型和routes.rb:

resources :orgs do
  resources :lists do
    resources :posts do
      resources :replies
    end
  end
end

所有这些关系都是一对多的,即列表总是属于1个组织,一个帖子总是属于1个列表等。我们非常清楚对多嵌套路由的普遍厌恶,但是有意识地决定朝着这个方向前进。

不幸的是,这意味着当您想要链接到编辑回复时,您必须写:

edit_org_list_post_reply_path( reply.post.list.org, reply.post.list, reply.list, reply )

感觉非常愚蠢。

我希望能够做到这样的事情:

fast_path( action: :edit, model: reply, type: :path )

并使用回复仅属于一个帖子的事实,该帖子属于一个列表等,以解决其余问题。类似的东西:

def fast_path options
  action = options[:action]
  model = options[:model]
  path_or_url = options[:type]

  model_fields = {
    reply: [:org, :list, :post]
    post: [:org, :list],
    list: [:org]
  }[model.class.name]

  arguments = model_fields.map { |field| model.send(field) } + [model]
  named_route_name = model_fields.join("_") + "_" + path_or_url
  named_route_name = action + "_" + named_route_name if action

  send(named_route_name, arguments)
end

虽然我没有证实这是有效的或代码特别好。

然而,我的同事之前做过类似的事情,在那里他以更加愉快的方式覆盖了许多命名路线。他声称它只能导致痛苦,绝望和痛苦,并且正在努力防止这些尝试超出我们的代码。

我很高兴出错,所以请告诉我们您的想法!

2 个答案:

答案 0 :(得分:1)

如果您不想覆盖路径助手(并且毫无疑问有充分的理由不这样做),您可以改为向Reply模型添加方法,如下所示:

def path_args  
  [post.list.org, post.list, post, self]
end

然后只需致电:edit_org_list_post_reply_path(*reply.path_args)

答案 1 :(得分:1)

您考虑过shallow nesting吗?

resources :orgs, shallow: true do
  resources :lists, shallow: true do
    resources :posts, shallow: true do
      resources :replies
    end
  end
end

然后你仍然可以获得所有集合的深层路径,但是所有成员的路径都很浅:

+---------------------+-----------+---------------------------------------+-------------------+
| Helper              | HTTP Verb | Path                                  | Controller#Action |
+---------------------+-----------+---------------------------------------+-------------------+
| post_replies_path   | GET       | /posts/:post_id/replies(.:format)     | replies#index     |
|                     | POST      | /posts/:post_id/replies(.:format)     | replies#create    |
| new_post_reply_path | GET       | /posts/:post_id/replies/new(.:format) | replies#new       |
| edit_reply_path     | GET       | /replies/:id/edit(.:format)           | replies#edit      |
| reply_path          | GET       | /replies/:id(.:format)                | replies#show      |
|                     | PATCH     | /replies/:id(.:format)                | replies#update    |
|                     | PUT       | /replies/:id(.:format)                | replies#update    |
|                     | DELETE    | /replies/:id(.:format)                | replies#destroy   |
| list_posts_path     | GET       | /lists/:list_id/posts(.:format)       | posts#index       |
|                     | POST      | /lists/:list_id/posts(.:format)       | posts#create      |
| new_list_post_path  | GET       | /lists/:list_id/posts/new(.:format)   | posts#new         |
| edit_post_path      | GET       | /posts/:id/edit(.:format)             | posts#edit        |
| post_path           | GET       | /posts/:id(.:format)                  | posts#show        |
|                     | PATCH     | /posts/:id(.:format)                  | posts#update      |
|                     | PUT       | /posts/:id(.:format)                  | posts#update      |
|                     | DELETE    | /posts/:id(.:format)                  | posts#destroy     |
| org_lists_path      | GET       | /orgs/:org_id/lists(.:format)         | lists#index       |
|                     | POST      | /orgs/:org_id/lists(.:format)         | lists#create      |
| new_org_list_path   | GET       | /orgs/:org_id/lists/new(.:format)     | lists#new         |
| edit_list_path      | GET       | /lists/:id/edit(.:format)             | lists#edit        |
| list_path           | GET       | /lists/:id(.:format)                  | lists#show        |
|                     | PATCH     | /lists/:id(.:format)                  | lists#update      |
|                     | PUT       | /lists/:id(.:format)                  | lists#update      |
|                     | DELETE    | /lists/:id(.:format)                  | lists#destroy     |
| orgs_path           | GET       | /orgs(.:format)                       | orgs#index        |
|                     | POST      | /orgs(.:format)                       | orgs#create       |
| new_org_path        | GET       | /orgs/new(.:format)                   | orgs#new          |
| edit_org_path       | GET       | /orgs/:id/edit(.:format)              | orgs#edit         |
| org_path            | GET       | /orgs/:id(.:format)                   | orgs#show         |
|                     | PATCH     | /orgs/:id(.:format)                   | orgs#update       |
|                     | PUT       | /orgs/:id(.:format)                   | orgs#update       |
|                     | DELETE    | /orgs/:id(.:format)                   | orgs#destroy      |
+---------------------+-----------+---------------------------------------+-------------------+