You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 06:15:38