繁体   English   中英

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

[英]Devise routing: is there a way to remove a route from Rails.application.routes?

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

如何从Rails.application.routes删除路由? draw块中,还是之后?


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

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

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

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

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


以下是我最后所做的事情,这是由何塞·瓦利姆引用的赏金获胜者所建议的:

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

delete '/person', :to => 'people#destroy'

然后在我现有的people_controller.rb ,我添加了一个no-op方法:

def destroy
  render :nothing => true
end

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

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

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

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

是的,有点。 您可以完全覆盖使用的设备控制器并编写您自己的设备(如果需要,继承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

只给你两条路线[: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"}

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

class SessionsController < Devise::SessionsController

  def new
    super
  end

  def create
    super
  end

end

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

第二次编辑

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

as :user do
  get  "sign_in", :to => "devise/sessions#new"
  post "sign_in", :to => "devise/sessions#create"
  ...
end

得到:

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

第三编辑

此外,您可以通过创建初始化程序来覆盖负责创建这些路由的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

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

此外

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

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

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

实际上devise_for确实支持:skip:only ,例如( docs ):

devise_for :user, :skip => :registration

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

更新:

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

# config/routes.rb
constraints lambda {|req| req.url =~ /users/ && req.delete? ? false : true} do
  devise_for :users
end

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

我找到了一个使用Devise 4.2.0和Rails 5.0.1的简单解决方案。 认为这将适用于Rails 4,而且我不确定Devise的旧版本。

创建一个覆盖devise_*路径助手的初始化器。 示例方法是devise_sessiondevise_passworddevise_confirmationdevise_unlockdevise_registration 查看来源

通过为文件名提供更大的字母数字值,确保在Devise初始化程序之后加载初始化程序。

例如,Devise使用:new:create:show actions创建:确认路由。 我只想要:create动作。

# config/initializers/devise_harden.rb
module ActionDispatch::Routing
  class Mapper

    # Override devise's confirmation route setup, as we want to limit it to :create
    def devise_confirmation(mapping, controllers)
      resource :confirmation, only: [:create],
               path: mapping.path_names[:confirmation], controller: controllers[:confirmations]
    end
  end
end

现在POST /auth/confirmation是唯一POST /auth/confirmation的路由设置。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM