Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AbstractController::ActionNotFound with Controller Override #185

Closed
hwhelchel opened this issue Mar 14, 2015 · 4 comments
Closed

AbstractController::ActionNotFound with Controller Override #185

hwhelchel opened this issue Mar 14, 2015 · 4 comments

Comments

@hwhelchel
Copy link

     Failure/Error: post :create, invalid_params
     AbstractController::ActionNotFound:
       Could not find devise mapping for path "/api/registrations?email=test%40example.com&password=secret".
       This may happen for two reasons:

       1) You forgot to wrap your route inside the scope block. For example:

         devise_scope :user do
           get "/some/route" => "some_devise_controller"
         end

       2) You are testing a Devise controller bypassing the router.
          If so, you can explicitly tell Devise which mapping to use:

          @request.env["devise.mapping"] = Devise.mappings[:user]

Version: 0.1.31
Devise Version: 3.4.1

Routes:

Rails.application.routes.draw do

  resource :health, only: :show

  namespace :api do
    mount_devise_token_auth_for 'Account', at: 'auth', skip: [:omniauth_callbacks], controllers: {
      registrations: 'api/registrations'
    }

    # ...
  end


  get "*path", to: "application#index"
  root 'application#index'
end

Auth routes

                         Prefix Verb   URI Pattern                          Controller#Action
                         health GET    /health(.:format)                    healths#show
        new_api_account_session GET    /api/auth/sign_in(.:format)          devise_token_auth/sessions#new
            api_account_session POST   /api/auth/sign_in(.:format)          devise_token_auth/sessions#create
    destroy_api_account_session DELETE /api/auth/sign_out(.:format)         devise_token_auth/sessions#destroy
           api_account_password POST   /api/auth/password(.:format)         devise_token_auth/passwords#create
       new_api_account_password GET    /api/auth/password/new(.:format)     devise_token_auth/passwords#new
      edit_api_account_password GET    /api/auth/password/edit(.:format)    devise_token_auth/passwords#edit
                                PATCH  /api/auth/password(.:format)         devise_token_auth/passwords#update
                                PUT    /api/auth/password(.:format)         devise_token_auth/passwords#update
cancel_api_account_registration GET    /api/auth/cancel(.:format)           api/registrations#cancel
       api_account_registration POST   /api/auth(.:format)                  api/registrations#create
   new_api_account_registration GET    /api/auth/sign_up(.:format)          api/registrations#new
  edit_api_account_registration GET    /api/auth/edit(.:format)             api/registrations#edit
                                PATCH  /api/auth(.:format)                  api/registrations#update
                                PUT    /api/auth(.:format)                  api/registrations#update
                                DELETE /api/auth(.:format)                  api/registrations#destroy
       api_account_confirmation POST   /api/auth/confirmation(.:format)     devise_token_auth/confirmations#create
   new_api_account_confirmation GET    /api/auth/confirmation/new(.:format) devise_token_auth/confirmations#new
                                GET    /api/auth/confirmation(.:format)     devise_token_auth/confirmations#show
        api_auth_validate_token GET    /api/auth/validate_token(.:format)   devise_token_auth/token_validations#validate_token

Override Controller:

class Api::RegistrationsController < DeviseTokenAuth::RegistrationsController
  def create
  end

  def update
  end

  def destroy
  end

  def edit
  end

  def new
  end

  def cancel
  end
end

Do you have any recommendations on what could be the issue? Looks like the env['devise.mapping'] is not being set successfully in ActionDispatch::Routing::Mapper#devise_scope. I don't have much experience with routing constraints so I tried devise's recommendation:

Rails.application.routes.draw do

  resource :health, only: :show


  namespace :api do
    mount_devise_token_auth_for 'Account', at: 'auth', skip: [:omniauth_callbacks], controllers: {
      registrations: 'api/registrations'
    }
    devise_scope :api_account do
      post 'registrations' => 'registrations#create'
    end
  end

  get "*path", to: "application#index"
  root 'application#index'
end

But the error persisted. Thanks!

@hwhelchel
Copy link
Author

I think I figured out the issue.
DeviseTokenAuth ActionDispatch::Routing::Mapper#mount_devise_token_auth_for calls #devise_for on line 25 which calls devise_scope with the :api_account parameter. Devise.add_mappings(resource, opts) handles the namespacing and returns :api_account as the mapping name. Then once that finishes back in ActionDispatch::Routing::Mapper#mount_devise_token_auth_for on line 46 devise_scope is called again but this time the parameter is :account. When the lambda constraint is called the scope is :account and Devise.mappings[:account] is nil causing it to blow up.

@lynndylanhurley
Copy link
Owner

Thanks for the detailed report @hwhelchel!

Nesting the mount_devise_token_auth_for call within a namespace / scope has been really tricky to implement. The issue is that Rails wants the controllers to share the same namespace as the routes, but the controller nesting can't be controlled when the controllers live inside of a gem.

So the solution was to implement a hack that un-nests the routes, re-constructs the intended path, and then mounts the routes at the root level to the intended path. This happens at around this point in the code. Devise itself has a similar mechanism.

But there is an issue where sometimes the namespacing adds a prefix to the path (api_ in your case).

I'll keep trying to re-produce this error so I can write a test against it. If you can find a fix, please send me a PR.

@lynndylanhurley
Copy link
Owner

Also, can you try using the latest beta version? (Currently 0.1.32.beta8)

@zachfeldman
Copy link
Contributor

Hi there @hwhelchel ,

In an effort to cleanup this project and prioritize a bit, we're marking issues that haven't had any activity in a while with a "close-in-7-days" label. If we don't hear from you in about a week, we'll be closing this issue. Obviously feel free to re-open it at any time if it's the right time or this was done in error!

If you are still having the issue (especially if it's a bug report) please refer to our new Issue Template to provide some more details to help us solve it.

Hope all is well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants