【问题标题】:How should I handle edit and update action when I use Form Object?使用表单对象时应该如何处理编辑和更新操作?
【发布时间】:2013-06-12 11:19:58
【问题描述】:

我有以下表单对象来管理复杂的嵌套表单。

表格

= simple_form_for(@profile_form, :url => profiles_path) do |f|
  ...

路线

resources :profiles

控制器

class ProfilesController < ApplicationController
  def new
    @profile_form = ProfileForm.new
  end

  def edit
    @profile_form = ProfileForm.new(params[:id])
  end

  def create
    @profile_form = ProfileForm.new
    if @profile_form.submit(params[:profile_form])
      redirect_to @profile_form.profile, notice: 'Profile was successfully created.'
    else
      render action: "new"
    end
  end

  def update
    @profile_form = ProfileForm.new(params[:id])
    if @profile_form.submit(params[:profile_form])
      redirect_to @profile_form.profile, notice: 'Profile was successfully updated.'
    else
      render action: "edit"
    end
  end
end

表单对象

class ProfileForm
  include ActiveModel::Validations
  include ActiveModel::Conversion
  extend ActiveModel::Naming

  def initialize(profile_id = nil)
    if profile_id
      @profile = Profile.find(profile_id)
      @person = profile.person
    end
  end
  ...
  def submit(params)
    profile.attributes = params.slice(:available_at)
    person.attributes = params.slice(:first_name, :last_name)

    if valid?
      profile.save!
      person.save!
      true
    else
      false
    end
  end
  def self.model_name
    ActiveModel::Name.new(self, nil, "Profile")
  end

  def persisted?
    false
  end
end

但是现在当我使用这个表单编辑对象时,create 动作被调用了。 那么我应该如何重构这个表单呢?下面update 上的代码会创建另一个 Profile 对象。

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-3 forms object


    【解决方案1】:

    simple_form_for 在内部使用form_for 来完成它的工作。 form_for 使用方法persisted? 来确定对象是否已经持久化在数据库中。如果它已经被持久化form_for 将生成一个带有方法 PUT 的表单来更新对象,否则它将生成一个带有方法 POST 的表单来创建新对象。因此,您必须为您的表单对象实现persisted? 方法。你可以这样实现它:

    class ProfileForm
      # ...
      def persisted?
        @person.persisted? && @profile.persisted?
      end
      # ...
    end
    

    更新如果@personnil,即没有Person 关联到Profile,我想你会创建一个新的Person 关联到@ 987654333@。在这种情况下,只要至少@profilepersisted?,就可以安全地假设ProfileFormpersisted?,因此:

    class ProfileForm
      # ...
      def persisted?
        @profile.persisted?
      end
      # ...
    end
    

    更新为避免undefined local variable or method `id' 错误,您必须为ProfileForm 定义id 方法,如下所示:

    class ProfileForm
      # ...
      def id
        @profile.id
      end
      # ...
    end
    

    【讨论】:

    • 好的,我明白了,谢谢。但是如何更改表单网址:= simple_form_for(@profile_form, :url =&gt; profiles_path) do |f| 我收到错误:undefined local variable or method `id' for #&lt;ProfileForm:0x007fe9e7a39070&gt;
    • 如果@person 为零怎么办?
    • 添加to_param 方法后我仍然有同样的错误。看起来问题出在 url 上。
    【解决方案2】:
    replace
    
      = simple_form_for(@profile_form, :url => profiles_path) do |f|
    
       with
    
       = simple_form_for(@profile_form, :url => {:controller => "profiles"}) do |f|
    

    【讨论】:

    • 不,没有任何改变。表单 url 仍然是:操作:/profiles 方法:post
    【解决方案3】:

    看这里:http://apidock.com/rails/ActionView/Helpers/FormHelper/apply_form_for_options!

    如果你想更新你的记录,你应该编写方法ProfileForm#persisted?,以便它返回true

    【讨论】:

    • 我设置的持久化?到false
    猜你喜欢
    • 2021-10-25
    • 1970-01-01
    • 2017-03-03
    • 1970-01-01
    • 1970-01-01
    • 2011-06-08
    • 1970-01-01
    • 2015-01-17
    • 1970-01-01
    相关资源
    最近更新 更多