Rails 5.2使用devise-security gem遇两类错误:控制器未找到与路由不匹配
搞定Rails 5.2下devise-security的两个烦人错误
这俩问题我之前帮同行排查过,都是Rails 5.2搭配devise-security时容易踩的配置坑,给你一步步捋清楚怎么修复:
核心原因
不管是「Devise controller not found」还是访问根路径时的路由错误,本质都是password_expirable模块需要的控制器和路由没有正确配置,devise找不到对应的处理逻辑才报错的。
步骤1:确认devise-security的初始化配置
先确保你已经跑过安装命令(没跑过现在赶紧补):
rails generate devise_security:install
这个命令会生成你已经有的config/initializers/devise-security.rb,还会自动给config/routes.rb加必要的路由映射。如果发现路由里没加上,手动补这段到devise_for :users里:
devise_for :users, controllers: { password_expired: 'devise/password_expired' # 要是用了其他devise-security模块,比如session_limitable,也可以对应加上控制器映射 }
步骤2:补全缺失的PasswordExpired控制器
有时候安装命令不会自动生成这个控制器,导致devise找不到它。手动在app/controllers/devise/目录下新建password_expired_controller.rb,内容如下:
class Devise::PasswordExpiredController < DeviseController prepend_before_action :require_no_authentication, only: [:new, :create] prepend_before_action :authenticate_scope!, only: [:edit, :update] def show @user = current_user end def update @user = current_user if @user.update(password_expired_params) sign_in(@user, bypass: true) redirect_to after_password_expired_update_path_for(@user) else render :show end end private def password_expired_params params.require(resource_name).permit(:password, :password_confirmation) end def after_password_expired_update_path_for(resource) stored_location_for(resource) || root_path end end
这个控制器专门处理密码过期后的展示和更新逻辑,补上之后「Devise controller not found」的错误就会消失。
步骤3:验证路由是否生效
跑一下rails routes命令,看看有没有出现类似下面的路由:
password_expired_show GET /users/password_expired(.:format) devise/password_expired#show password_expired_update PUT /users/password_expired(.:format) devise/password_expired#update
要是能看到这俩路由,说明配置没问题了。这时候再访问根路径,密码过期的用户会被正确重定向到密码更新页面,不会再触发路由错误。
最后再检查下你的User模型,devise模块里已经加了:password_expirable,这个是对的,不用改。
内容的提问来源于stack exchange,提问作者rigyt
相关产品推荐
相关产品推荐

