如果表单本身从未持久化,您能否使表单对象适用于新操作和编辑操作?

Posted

技术标签:

【中文标题】如果表单本身从未持久化,您能否使表单对象适用于新操作和编辑操作?【英文标题】:Can you make a form object work for new and edit actions if the form itself is never persisted? 【发布时间】:2021-10-25 16:50:18 【问题描述】:

我正在尝试使表单对象适用于 new Useredit User 操作。表单对象通过它的save 方法创建或更新User,但表单对象本身永远不会持久化,因此即使我在simple_form_for url 中指定了不同的路由,Rails 也总是尝试进行 POST。

有没有办法让它对这两种操作都起作用?

UsersController.rb:

class Admin::UsersController < AdminController
  def new
    @user_form = UserForm.new(account_id: current_account.id)
  end

  def create
    @user_form = UserForm.new(user_form_params)
    if @user = @user_form.save
      flash[:success] = "User created"
      redirect_to admin_user_path(@user)
    else
      render "new"
    end
  end

  def edit
    @user_form = UserForm.new(existing_user: @user, account_id: current_account.id)
  end

  def update
    if @user.update(user_form_params)
      flash[:success] = "User saved"
      redirect_to admin_user_path(@user)
    else
      render "edit"
    end
  end
end

UserForm.rb

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

  attr_accessor :fname, :lname, :email

  def initialize(params = )
    super(params)
    @account = Account.find(account_id)
    @user = existing_user || user
  end

  def user
    @user ||= User.new do |user|
      user.fname = fname
      user.lname = lname
      user.email = email
    end
  end
    
  def save
    @user.save
    @user
  end
end

_form.html.erb

<%= simple_form_for @user_form, url: (@user.present? ? admin_user_path(@user) : admin_users_path) do |f| %>

    <%= f.input :fname  %>
    <%= f.input :lname %>
    <%= f.input :email %>
    <%= f.submit %>
    
end

新建/创建流程运行良好,但编辑现有 User 会返回

No route matches [POST] "/admin/users/69"

【问题讨论】:

如果您查看我给您的上一个问题的答案,它实际上解决了这个问题。 @max 对不起,我又问了一遍,但我以为我解释错了。你能解释一下to_model 方法的作用吗?它确实解决了路由问题 在普通型号上to_model 只是返回自我。当您将记录传递给form_forlink_to 时,多态路由助手调用to_model.model_name.route_keysingular_route_key,具体取决于模型是否为persisted?。传递[:admin, @user_form] 将导致多态路由助手使用admin_users_path 而不仅仅是users_path。 api.rubyonrails.org/v6.1.4/classes/ActionDispatch/Routing/… 【参考方案1】:
class UserForm
  # ...

  def to_model
    @user
  end
end
<%= simple_form_for @user_form, url: [:admin, @user_form] do |f| %>
    <%= f.input :fname  %>
    <%= f.input :lname %>
    <%= f.input :email %>
    <%= f.submit %>
end

当您将记录传递给form_for(SimpleForm 包装)、form_withlink_to 时,多态路由助手调用to_model.model_name.route_keysingular_route_key,具体取决于模型是否为persisted?。传递[:admin, @user_form] 将导致多态路由助手使用admin_users_path 而不仅仅是users_path

在普通模型上to_model 只是返回自我。

https://api.rubyonrails.org/v6.1.4/classes/ActionDispatch/Routing/PolymorphicRoutes.html

【讨论】:

以上是关于如果表单本身从未持久化,您能否使表单对象适用于新操作和编辑操作?的主要内容,如果未能解决你的问题,请参考以下文章

Twig - 迭代表单字段

如何使事件回调进入我的 win 表单线程安全?

多页表单:使无效字段成为焦点

你如何使用表单对象来编辑另一个类实例?

如何确定哪个子窗体有焦点

如何使用 symfony 4 创建登录验证表单