Riptyde4
Riptyde4

Reputation: 5480

Could not find devise mapping for controller path

I know there are a ton of questions with this same problem but none of the solutions seem to be working for my situation.

I've defined my own sessions, registrations, and users controllers since I'm using an API with token authentication, but I can't seem to get my routes/scoping working.

I get the following error message upon trying to run an Spec test on my sessions controller (which inherits from DeviseController)

 Failure/Error: post :create,  credentials

 AbstractController::ActionNotFound:
   Could not find devise mapping for path "/api/v1/sessions/create?user_login%5Bemail%5D=rosina%40russel.name&user_login%5Bpassword%5D=12345678".
   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]

I've actually done both of these things based on other answers that I've read, but I don't think its done correctly for my specific situation.

Here is the spec test I'm trying to run

describe "POST #create" do

before(:each) do
 @user = FactoryGirl.create :user
 @user.skip_confirmation!
 @request.env['devise.mapping'] = Devise.mappings[:user]
end

context "when the credentials are correct" do

  before(:each) do
    credentials = { user_login: { :email => @user.email, :password => "12345678"} }
    post :create,  credentials
  end

  it "returns the user record corresponding to the given credentials" do
    @user.reload
    user_response = JSON.parse(response.body, symbolize_names: true)
    expect(user_response[:auth_token]).to eql @user.auth_token
  end

  it { should respond_with :created }
end
end

As you can see, I'm specifying what it's saying that I haven't specified.

Here is the snippet from my routes.rb before the definition of my API in it's namespace:

namespace :api, defaults: { format: :json } do
  namespace :v1 do
    devise_for :users, skip: [:sessions, :registrations]      

    devise_scope :user do
      post 'sessions', to: 'sessions#create'
      delete 'sessions', to: 'sessions#destroy'
    end

If anyone sees anything from with this please let me know, I'd love to test my controller...

And yes, my sessions_controller is located in app/controllers/api/v1/sessions_controller.rb and it is properly defined as class API::V1::SessionsController < DeviseController

I noticed that devise_for is supposed to SET Devise.mapping but that seems to not be happening at all!

Upvotes: 1

Views: 875

Answers (2)

Riptyde4
Riptyde4

Reputation: 5480

I should've done this right away. I sent Devise.mappings.inspect to the logger and it read that the mapping was stored in :api_v1_user so the key in the mapping hash corresponds to the namespace that you wrote devise_for in... hopefully this will help others

Upvotes: 1

MilesStanfield
MilesStanfield

Reputation: 4649

Based on your routes, API is in json format. So you need to specify that when sending post method. Which is why I think rspec is complaining about that route not existing because it doesn't know to use json. Try changing this

post :create, credentials

to this

post :create, credentials, format: :json

Upvotes: 0

Related Questions