当创建失败时,如何持久化实例化的嵌套表单对象



我有型号SoftwareVersion。软件has_many版本与has_one :first_version

class Software < ApplicationRecord
has_many :versions
has_one :first_version, -> { order(created_at: :asc) },
class_name: "Version", dependent: :destroy 
accepts_nested_attributes_for :versions
end
class Version < ApplicationRecord
belongs_to :software
end

我正在new控制器操作中构建嵌套对象。

class SoftwaresController < ApplicationController

def new
@software = current_account.softwares.build
@software.build_first_version
end
def create
@software = current_account.softwares.build(software_params)
if @software.save
redirect_to software_path(@software)
else
render :new
end
end
def software_params
params.require(:software).permit(
:name,
first_version_attributes: %i[id release_date],
)
end
end

形式:

<%= simple_form_for :software do |f| %>
<%= f.input :name %>

<%= f.simple_fields_for :first_version do |v|%>
<%= v.input :release_date %>
<% end %>
<% end %>

使用上面的代码,如果在创建过程中出现故障,即使对象本身及其父对象还没有id,嵌套对象也会被持久化,因此错误会显示在每个具有无效值的字段下。同时,如果我注释掉构建嵌套对象的行,表单不会中断,只是不会显示嵌套字段这很好

现在,由于该表单在newedit视图中被重用,并且我不想让用户通过该表单编辑:first_version,也不想在@software.new_record?的情况下依赖该视图有条件地呈现它,所以我将嵌套对象放在全局变量中,并将嵌套表单指向该变量,希望在edit视图中也能获得相同的结果,因为不存在全局变量。

def new
@software = current_account.softwares.build
@first_version = @software.build_first_version
end

形式:

<%= simple_form_for :software do |f| %>
<%= f.input :name %>

<%= f.simple_fields_for @first_version do |v|%>
<%= v.input :release_date %>
<% end %>
<% end %>

问题:如果在创建过程中出现问题,对象将不再持久化,并且视图将由于@first_versionnil而中断。那么,为什么当我执行@parent.build_nested_object时,嵌套对象被持久化,而当执行@nested_object = @parent.build_nested_object时却没有呢?

通过创建更多i_vars来解决问题可能会导致错误。我认为最好的选择是根据条件禁用该字段,并将您的视图更改为以下内容。

<%= simple_form_for @software do |f| %>
<%= f.input :name %>
<%= f.simple_fields_for @software.first_version || @software.build_first_version do |v| %>
<%= v.input :release_date, disabled: (true if @software.first_version.id) %>
<% end %>
<% end %>

使用此视图意味着您只能在控制器上初始化@software

class SoftwaresController < ApplicationController
def new
@software = current_account.softwares.build
end
end

最新更新