设计路由:有没有办法从Rails.application.routes中删除路由?

ipd*_*ipd 20 routes ruby-on-rails devise ruby-on-rails-3

devise_for创建包含DELETE路由的路由,我们要删除它,并且devise_for不支持:except:only选项.

如何从中删除路线Rails.application.routes?在draw街区或之后?


以下是错误的详细信息,这是我们需要删除路由的原因.

  • 我们向自定义UJS控制器操作发出DELETE请求

  • 在控制器操作中,我们删除了我们想要的内容,然后执行302重定向.这是一个坏主意,我们已经通过返回一些JSON来纠正它.

  • 一些客户端在收到302后会向重定向发出一个新的DELETE请求,该请求路由到Devise删除路由!从而无意中删除了这个人!让人惊讶.我们假设这将是一个GET.不好的假设.

这个错误已经修复,但我想删除路由.


以下是我最后所做的事情,这是由Jose'Valim引用的赏金获胜者所建议的:

config/routes.rb,我在devise_for呼叫上面添加了这个,它设置了其余的'people'路由:

delete '/person', :to => 'people#destroy'
Run Code Online (Sandbox Code Playgroud)

然后在我现有的people_controller.rb,我添加了一个无操作方法:

def destroy
  render :nothing => true
end
Run Code Online (Sandbox Code Playgroud)

我仍然有点恼火,没有一种简单的方法可以从RouteSet中删除路由.此外,delete路由仍然存在于设计控制器,但它不会被调用,因为rails查找第一个匹配config/routes.rb并返回它.

sko*_*rks 13

以下是Jose Valim(设计的作者)就此主题所说的话:

无法单独删除路线.或者您使用:跳过全部删除并手动绘制您需要的路径,或者通过在config/routes.rb中首先定义到同一路径的路由来覆盖此路由.

所以对你的问题的简短回答是否定的,你不能删除那条路线.你当然可以尝试修补devise_for方法,但这将是一个有点参与的事业(一天或几个努力).我只是使用:skip选项,然后实现你想要的那个控制器的路由,而不是那个你没有的路由.


Kru*_*ule 8

是的,有点.您可以完全覆盖使用的设备控制器并编写您自己的设备(如果需要,继承Devise).这个维基页面可以作为指导.

编辑

为什么我说有点:)

覆盖会话使用:

devise_for :users, :controllers => { :sessions => 'custom_devise/sessions'}, :skip => [:sessions] do
  get 'sign_in' => 'custom_devise/sessions#new', :as => :new_user_session
  post 'sign_in' => 'custom_devise/sessions#create', :as => :user_session
end
Run Code Online (Sandbox Code Playgroud)

只给你两条路线[:get,:post],但不是:destroy

new_user_session GET  /sign_in(.:format) {:controller=>"custom_devise/sessions", :action=>"new"}
user_session POST /sign_in(.:format) {:controller=>"custom_devise/sessions", :action=>"create"}
Run Code Online (Sandbox Code Playgroud)

所以,实际上,你跳过了破坏/删除路由.现在在控制器中你可以去:

class SessionsController < Devise::SessionsController

  def new
    super
  end

  def create
    super
  end

end
Run Code Online (Sandbox Code Playgroud)

您现在可以重复注册,密码和解锁的过程.

第二次编辑

啊,是的还有另一种更简单的方法.您可以使用devise_scope 手动创建路径(文档),也称为"as"而不覆盖:

as :user do
  get  "sign_in", :to => "devise/sessions#new"
  post "sign_in", :to => "devise/sessions#create"
  ...
end
Run Code Online (Sandbox Code Playgroud)

得到:

sign_in GET  /sign_in(.:format) {:controller=>"devise/sessions", :action=>"new"}
        POST /sign_in(.:format) {:controller=>"devise/sessions", :action=>"create"}
Run Code Online (Sandbox Code Playgroud)

第三编辑

此外,您可以通过创建初始化程序来覆盖负责创建这些路由的Devise的一部分(仅用于没有设计"破坏"路由的应用程序):

module ActionDispatch::Routing
  extend ActionDispatch::Routing
  class Mapper

    protected
      def devise_session(mapping, controllers) #:nodoc:
        resource :session, :only => [], :controller => controllers[:sessions], :path => "" do
          get   :new,     :path => mapping.path_names[:sign_in],  :as => "new"
          post  :create,  :path => mapping.path_names[:sign_in]
        end
      end

      def devise_registration(mapping, controllers) #:nodoc:
        path_names = {
          :new => mapping.path_names[:sign_up],
          :cancel => mapping.path_names[:cancel]
        }

        resource :registration, :only => [:new, :create, :edit, :update], :path => mapping.path_names[:registration],
                 :path_names => path_names, :controller => controllers[:registrations] do
          get :cancel
        end
      end
  end
end
Run Code Online (Sandbox Code Playgroud)

请注意,此修补程序会删除Devise中使用的所有销毁路由("会话"和"注册"中只有两个),并且仅针对此特定情况进行修复.

此外

您还可以添加:除路线选项外.为了做到这一点,你必须添加devise_for方法(从原始复制并修改以满足你的愿望)到Mapper类,所以它将[:except]成员的成员发送到上面提到的(在代码中)私有方法..然后你应该修改那些根据条件添加路由.

最快,最脏的方法,就是添加@scope [:except] = options [:except]然后修改私有方法,以便除了哈希(如果你决定使用细粒度路由控制,如::except => {:sessions => [:destroy]},从而使得:skip过时)或数组(如果要:except => [:destroy]在添加路由之前检查所有路由中的此特定操作,请执行以下操作:).

无论如何,有很多方法可以实现您的需求.你可以选择你认为最适合的那个.


dwh*_*len 7

其实devise_for不支持:skip:only,例如(文档):

devise_for :user, :skip => :registration
Run Code Online (Sandbox Code Playgroud)

这将跳过所有注册控制器的路由,而不是具体的路由.然后,您可以实施所需的路线.这似乎比在事后删除路线更干净.

更新:

另一种可能的解决方案是使用Rails的高级约束功能来完全阻止不需要的路由:

# config/routes.rb
constraints lambda {|req| req.url =~ /users/ && req.delete? ? false : true} do
  devise_for :users
end
Run Code Online (Sandbox Code Playgroud)

这是一篇关于使用lambdas进行路径约束的文章.这里解释请求对象.这可能是最简单的解决方案.