devise_scope找不到映射

时间:2019-07-15 19:46:38

标签: ruby-on-rails devise ruby-on-rails-5.2

我正在使用devise_scope定义我的路线,以便缩短我不使用的生成路线的列表。

我有这个路线文件:

devise_for :users, class_name: 'Identity::User', skip: :all

        namespace :users do
          devise_scope :user do
            post 'sign_in', controller: "/api/v1/identity/sessions", action: :create
            delete 'sign_out', controller: "/api/v1/identity/sessions", action: :destroy
            post '/', controller: "/api/v1/identity/registrations", action: :create
          end

我已经确认这会产生预期的路线。按下sign_in路由后,它似乎确实击中了扩展SessionController的适当控制器Devise::SessionsController。但是,出现以下错误:

Could not find devise mapping for path "/api/v1/users/sign_in".
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]


Completed 404 Not Found in 1ms (ActiveRecord: 0.0ms)

我认为devise_for不能正确设置我需要的路线吗?

编辑:解决方案,但不理想。

在我的情况下,问题是devise_for映射不正确。完整的路由包括另一个我忽略粘贴的名称空间:

namespace :api do
devise_for :users, class_name: 'Identity::User', skip: :all

namespace :users do
  devise_scope :user do
    post 'sign_in', controller: "/api/v1/identity/sessions", action: :create
    delete 'sign_out', controller: "/api/v1/identity/sessions", action: :destroy
    post '/', controller: "/api/v1/identity/registrations", action: :create
  end
end
end

但是,如果我将devise移到api名称空间之外,则映射是正确的:

devise_for :users, class_name: 'Identity::User', skip: :all

namespace :api do

namespace :users do
  devise_scope :user do
    post 'sign_in', controller: "/api/v1/identity/sessions", action: :create
    delete 'sign_out', controller: "/api/v1/identity/sessions", action: :destroy
    post '/', controller: "/api/v1/identity/registrations", action: :create
  end
end
end

我使用嵌套的路由文件,因此这样做会破坏我的结构。有没有办法调整它以便在该api名称空间中使用它?

1 个答案:

答案 0 :(得分:1)

因此,基本上,我相信设备在命名空间时会尝试使用“设备”控制器。

因此,当在:api命名空间内部时,rails将寻找Api::Devise::Sessions(或类似的东西)控制器,而devise则只希望Devise::Sessions

在这种情况下该怎么办?

  1. 尝试devise_for :users, class_name: 'Identity::User', path: :api, skip: :all
  2. 您可以尝试使用scope :api do代替namespace :api do

    这会影响创建的路径,但Rails仍应寻找正确的设备控制器

  3. 明确告诉devise使用哪个控制器

以及第3点的外观如下:

namespace :api do
  devise_for :users, class_name: 'Identity::User', controllers: { session: "api/v1/sessions" }, skip: :all    
  namespace :users do
    devise_scope :user do
      post 'sign_in', controller: "/api/v1/identity/sessions", action: :create
      delete 'sign_out', controller: "/api/v1/identity/sessions", action: :destroy
      post '/', controller: "/api/v1/identity/registrations", action: :create
    end
  end
end