Rails Devise如何自定义/settings路由复用逻辑移除默认/users/edit路由
Devise自定义/settings/account替换默认/users/edit实现方案
1. 路由配置调整
修改config/routes.rb,跳过Devise默认生成的注册模块编辑、更新路由,移除默认/users/edit访问入口,同时将自定义设置页路由绑定Devise原生路由别名,保证内部跳转、路径辅助方法正常工作:
Rails.application.routes.draw do # 跳过Devise默认registrations模块全量路由,后续按需保留需要的默认路由 devise_for :users, skip: [:registrations] devise_scope :user do # 保留默认注册、注销路由 get 'users/sign_up' => 'devise/registrations#new', as: :new_user_registration post 'users' => 'devise/registrations#create', as: :user_registration delete 'users/sign_out' => 'devise/sessions#destroy', as: :destroy_user_session # 自定义账户设置路由,绑定Devise原生路由别名 get 'settings/account' => 'settings#account', as: :edit_user_registration patch 'settings/account' => 'settings#update_account' put 'settings/account' => 'settings#update_account' end root "home#index" # 其余设置页路由保持原有配置 get "settings/profile" => "settings#profile" get "settings/billing" => "settings#billing" get "settings/notifications" => "settings#notifications" end
绑定
edit_user_registration别名后,项目内所有调用edit_user_registration_path的位置(包括Devise内部自动生成的跳转链接)都会自动指向/settings/account,无需逐个修改路径引用。
2. 控制器逻辑补充
修改app/controllers/settings_controller.rb,添加账户更新动作,完全复用Devise原生校验、更新逻辑,兼容confirmable邮箱验证、密码校验、登录态保持等内置能力:
class SettingsController < ApplicationController before_action :authenticate_user! def profile end def account @user = current_user end def update_account @user = current_user update_params = account_params # 匹配Devise原生逻辑:密码字段留空时不更新密码 if update_params[:password].blank? update_params.delete(:password) update_params.delete(:password_confirmation) update_params.delete(:current_password) end if @user.update_with_password(update_params) # 兼容confirmable模块:邮箱变更时发送验证邮件 flash[:notice] = if @user.respond_to?(:pending_reconfirmation?) && @user.pending_reconfirmation? "账户更新成功,新邮箱验证邮件已发送,请完成验证后邮箱变更生效。" else "账户信息更新成功。" end # 更新完成后保持登录态,避免被Devise自动登出 bypass_sign_in @user, scope: :user redirect_to settings_account_path else render :account, status: :unprocessable_entity end end def billing end def notifications end private def account_params # 如需在账户页更新其他用户字段,直接添加到permit列表即可 params.require(:user).permit(:email, :password, :password_confirmation, :current_password) end end
3. 视图表单编写
在app/views/settings/account.html.erb中编写账户设置表单,提交地址直接使用Devise原生路由辅助方法,字段规则和默认实现保持一致:
<h1>账户设置</h1> <% if @user.errors.any? %> <div class="alert alert-danger"> <h3><%= pluralize(@user.errors.count, "个错误") %>导致保存失败:</h3> <ul> <% @user.errors.full_messages.each do |msg| %> <li><%= msg %></li> <% end %> </ul> </div> <% end %> <%= form_with(model: @user, url: user_registration_path, method: :patch, local: true) do |f| %> <div class="form-group"> <%= f.label :email, "登录邮箱" %> <%= f.email_field :email, class: "form-control" %> </div> <div class="form-group"> <%= f.label :password, "新密码(不修改请留空)" %> <%= f.password_field :password, class: "form-control" %> </div> <div class="form-group"> <%= f.label :password_confirmation, "确认新密码" %> <%= f.password_field :password_confirmation, class: "form-control" %> </div> <div class="form-group"> <%= f.label :current_password, "当前密码(修改邮箱/密码时必填)" %> <%= f.password_field :current_password, class: "form-control" %> </div> <div class="form-actions"> <%= f.submit "保存修改", class: "btn btn-primary" %> </div> <% end %>
效果验证
配置完成后重启Rails服务:
- 访问原默认路径
/users/edit会直接返回路由不存在错误,完全从可访问路由列表中移除 - 访问
/settings/account可正常进入账户编辑页,密码校验、邮箱验证、更新后登录态保持等逻辑和Devise原生行为完全一致,无兼容问题
内容的提问来源于stack exchange,提问作者bitsmyth
相关产品推荐
相关产品推荐

