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

如何通过UserForm表单对象加载现有User实例完成编辑操作?

问题根因

你遇到的问题核心有3个:

  1. UserForm 没有接收现有User实例的逻辑,也没有将User的属性同步到表单自身的可访问字段上,导致渲染表单时拿不到已有数据
  2. 原有UserForm的initialize方法存在逻辑缺陷,新建场景下没有user_id会直接抛出查询异常
  3. 控制器update动作没有走UserForm的逻辑,表单提交路径也没有区分新建/更新场景

修复方案

1. 修改 UserForm.rb

class UserForm
  include ActiveModel::Model
  include ActiveModel::Validations::Callbacks

  # 补充需要接收的参数
  attr_accessor :fname, :lname, :email, :account_id, :user_id, :user

  before_validation :sync_user_attributes

  def initialize(params = {})
    # 优先处理传入的已有User实例
    if params[:user].present?
      @user = params.delete(:user)
      # 把已有User的属性赋值给表单字段,渲染时就能拿到值
      self.fname = @user.fname
      self.lname = @user.lname
      self.email = @user.email
      self.account_id = @user.account_id
      self.user_id = @user.id
    end
    super(params)
    @account = Account.find(account_id)
  end

  # 新增判断场景的方法,给表单视图用
  def persisted?
    user_id.present?
  end

  def sync_user_attributes
    # 已有用户就更新属性,新用户就初始化
    @user ||= User.new
    @user.attributes = {
      fname: fname,
      lname: lname,
      email: email,
      account_id: @account.id
    }
  end
    
  def save
    # 验证通过后直接保存user即可,属性已经同步完成
    return false unless valid?
    @user.save
  end
end

2. 修改 UsersController.rb

class Admin::UsersController < AdminController
  # 编辑和更新动作前先加载对应User
  before_action :load_user, only: [:edit, :update]

  def new
    @user_form = UserForm.new(account_id: current_account.id)
  end

  def create
    @user_form = UserForm.new(user_form_params.merge(account_id: current_account.id))
    
    if @user_form.save
      flash[:success] = "User created"
      redirect_to admin_user_path(@user_form.user)
    else
      render "new"
    end
  end   
    
  def edit
    # 直接把查到的User传给表单
    @user_form = UserForm.new(user: @user)
  end

  def update
    @user_form = UserForm.new(user_form_params.merge(user: @user, account_id: current_account.id))
    if @user_form.save
      flash[:success] = "User updated"
      redirect_to admin_user_path(@user)
    else
      render "edit"
    end
  end

  private

  def load_user
    @user = current_account.users.find(params[:id])
  end

  # 补充表单参数白名单
  def user_form_params
    params.require(:user_form).permit(:fname, :lname, :email)
  end
end

3. 修改表单视图 form.html.erb

自动适配新建/更新的提交路径和请求方法:

<%= simple_form_for @user_form, url: @user_form.persisted? ? admin_user_path(@user_form.user) : admin_users_path, method: @user_form.persisted? ? :patch : :post do |f| %>
    <%= f.input :fname  %>
    <%= f.input :lname %>
    <%= f.input :email %>
<% end %>

内容的提问来源于stack exchange,提问作者pinkfloyd90

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 23:45:05