我有型号Software
和Version
。软件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
,嵌套对象也会被持久化,因此错误会显示在每个具有无效值的字段下。同时,如果我注释掉构建嵌套对象的行,表单不会中断,只是不会显示嵌套字段这很好
现在,由于该表单在new
和edit
视图中被重用,并且我不想让用户通过该表单编辑: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_version
是nil
而中断。那么,为什么当我执行@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