【问题标题】:Customize Rails' Default Resourceful Route Path自定义 Rails 的默认资源路由路径
【发布时间】:2015-09-26 08:59:44
【问题描述】:

TL;DR

我想更改 Rails 资源路由的默认行为,将所有资源的 create 路径移动到 /resources/new 而不是 /resources 的 POST。


设置

让我们假设这样指定的资源丰富的路线:

# routes.rb

resources :events


将生成的实际路线是:

$ rake routes

    Prefix Verb   URI Pattern                Controller#Action
    events GET    /events(.:format)          events#index
           POST   /events(.:format)          events#create
 new_event GET    /events/new(.:format)      events#new
edit_event GET    /events/:id/edit(.:format) events#edit
     event GET    /events/:id(.:format)      events#show
           PATCH  /events/:id(.:format)      events#update
           PUT    /events/:id(.:format)      events#update
           DELETE /events/:id(.:format)      events#destroy

注意create 操作是由 POST 到 /events 路径触发的。


现在,如果我想更改该路径,我可以根据每个资源“手动”进行:

# routes.rb

# I've placed the routes in this order, and used `as: "new_event"`,
# to avoid generating an `events_new` path helper.

post 'events/new' => 'events#create', as: "new_event"
resources :events, except: [:create]


这里是生成的路线:

$ rake routes

    Prefix Verb   URI Pattern                Controller#Action
 new_event POST   /events/new(.:format)      events#create
    events GET    /events(.:format)          events#index
           GET    /events/new(.:format)      events#new
edit_event GET    /events/:id/edit(.:format) events#edit
     event GET    /events/:id(.:format)      events#show
           PATCH  /events/:id(.:format)      events#update
           PUT    /events/:id(.:format)      events#update
           DELETE /events/:id(.:format)      events#destroy


太棒了! create 操作现在由/events/new 路径而不是/events 路径的POST 触发。

所有其他路由/助手的行为与以前完全相同 - 包括对 /events/new 的 GET 和 new_event 路径/url 助手。


问题

除了手动覆盖每个create 操作,有没有办法只更改用于该特定操作的默认路径?

如果做不到这一点,我还能使用什么其他方法来更改一堆资源丰富的路由,以便将它们的创建操作移至上述/new

谢谢!

【问题讨论】:

  • 我的猜测是你必须给 resources 打补丁才能做到这一点,但我强烈鼓励你不要这样做 - Rails 都是关于约定的,这会让其他会阅读您的代码的开发人员感到困惑。一种更明确的处理方式是使用包含修改后的发布操作的routing concern,并将except: :create 添加到每个resources 调用中。
  • 另外,您还可以定义一个custom_resources 方法,该方法将执行您已经手动执行的操作,在此过程中调用原始resources
  • 您第二条评论中的建议是我最终所做的。它工作得很好。如果您想将其重写为答案,我会将其标记为正确。

标签: ruby-on-rails ruby routing


【解决方案1】:

您可以通过添加一个在一个地方为您执行覆盖的模块来简化您的生活。例如:

module MyResources
  def my_resources(resource_name, opts = {}, &block)
    opts = opts.merge(except: [:create])

    resources(resource_name, opts, &block)
    post "#{resource_name}/new" => "#{resource_name}#create", as: "new_{resource_name}"    
  end
end

ActionDispatch::Routing::Mapper.__send__ :include, MyResources

然后在你的 routes.rb 中你可以这样做:

my_resources :events

【讨论】:

  • 你会推荐把这样的模块放在哪里?在路由文件中?例如,app/services?在lib?在初始化程序中?另外,我对我的红宝石不是超级感兴趣。您使用__send__ kosher 的方式是?这似乎是一只猴子正在被修补,可能违背了它的意愿。
猜你喜欢
  • 2011-01-17
  • 1970-01-01
  • 2014-08-22
  • 2019-07-02
  • 2014-12-24
  • 2015-04-19
  • 2020-10-13
  • 1970-01-01
  • 2016-09-28
相关资源
最近更新 更多