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

后端 未结 4 1144
温柔的废话
温柔的废话 2020-12-14 02:53

devise_for creates routes including a DELETE route, which we want to remove, and devise_for doesn\'t support an :except or :only

4条回答
  •  再見小時候
    2020-12-14 03:23

    Yes, kinda. You can completely overwrite devise controllers used and write your own (inheriting Devise's if needed). This wiki page can serve as guideline.

    Edit

    Why I have said kinda :)

    Overriding sessions using:

    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
    

    will give you only two routes [:get, :post], but not :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"}
    

    So, effectively, you skip destroy/delete route. Now in controller you can go:

    class SessionsController < Devise::SessionsController
    
      def new
        super
      end
    
      def create
        super
      end
    
    end
    

    You can now repeat the process for registrations, passwords and unlocks.

    Second Edit

    Ah, yes there is another, simpler way. You can manually create routes (documentation) using devise_scope also known as "as" without overriding:

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

    Gives:

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

    Third Edit

    Also, you could overwrite part of Devise in charge of creating these routes, (only to be used in applications that will have no devise "destroy" route whatsoever), by creating an initializer:

    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
    

    Note that this fix removes all destroy routes used in Devise (there are only two in "sessions" and "registrations") and is a fix only for this specific case.

    In addition

    You could also add :except option to routes. In order to do it, you must add devise_for method (copy it from original and modify to suit your wishes) to Mapper class so it sends [:except] member of options to above-mentioned (in code) private methods.. Then you should modify those to add routes based on conditions.

    Fastest, dirty way, would be to add @scope[:except] = options[:except] and then to modify private methods so that except hash (if you decide to have fine grained route control like: :except => {:sessions => [:destroy]}, thus making :skip obsolete) or array (if you want to remove this specific action from all routes, like: :except => [:destroy]) is checked before adding route.

    Anyway, there are plenty ways to achieve what you need. It's up to you to pick the one you think is best suited.

提交回复
热议问题