Ruby on rails Rails的“编辑”操作无法使用同一模型的多个实例正确填充表单
我是Rails新手,正在做我的第一个项目。另外,英语不是我的母语,所以请容忍我 我遇到的问题是,我有一个表单,该表单具有同一模型的多个实例,数据创建正确,但当我尝试编辑它时,表单以错误的方式填充 我正在制作一个应用程序来检查一切是否符合规则。 要检查的项目位于嵌套的关联章->子章->检查中 每次提交检查时,都会创建一个检查轮,并且每次检查的信息都会单独存储在检查结果中 查房Ruby on rails Rails的“编辑”操作无法使用同一模型的多个实例正确填充表单,ruby-on-rails,ruby,forms,Ruby On Rails,Ruby,Forms,我是Rails新手,正在做我的第一个项目。另外,英语不是我的母语,所以请容忍我 我遇到的问题是,我有一个表单,该表单具有同一模型的多个实例,数据创建正确,但当我尝试编辑它时,表单以错误的方式填充 我正在制作一个应用程序来检查一切是否符合规则。 要检查的项目位于嵌套的关联章->子章->检查中 每次提交检查时,都会创建一个检查轮,并且每次检查的信息都会单独存储在检查结果中 查房 has_many :check_results, inverse_of: :check_round, dependent:
has_many :check_results, inverse_of: :check_round, dependent: :destroy
accepts_nested_attributes_for :check_results, reject_if: proc { |att| att['observation'].blank? }
检查结果
belongs_to :check_round, optional: true, inverse_of: :check_results
belongs_to :check
章节
has_many :subchapters
分章
belongs_to: chapter
has_many: checks
检查
belongs_to :subchapter
has_many :check_results
该表单显示所有章节以及嵌套的子章节和检查。
每个检查都显示其名称,并有一个文本区域作为输入
用户可以填写一张或多张支票
<%= form_for(@check_round, :url => {:action => 'update', :client_id => @client.id, :project_id => @project.id}) do |f| %>
<% @chapters.each do |chapter| %>
<%= chapter.name %>
<% chapter.subchapters.each do |subchapter| %>
<%= subchapter.name %>
<% subchapter.checks.each do |check| %>
<%= f.fields_for :check_results do |result| %>
<%= check.name %>
<%= result.hidden_field(:check_id, :value => check.id) %>
<%= result.text_area(:observation, rows: 4, :id =>'obs' + check.id.to_s) %>
<% end %>
<% end %>
<% end %>
<% end %>
<% end %>
例如,如果我在编辑时提交check.id=3
具有observation=“bad”
,则无论其id如何,每个检查的观察值都具有“bad”
我想知道如何在“编辑”中显示除已创建的检查之外的所有空白检查
提前感谢您的时间 我相信它可以像您希望的那样工作(代码经过一些简化): 检查 edit.html.erb
<%= form_for(@check_round, :url => {:action => 'update'}) do |f| %>
<ul>
<% @chapters.each do |chapter| %>
<li>
<%= chapter.name %>
chapter
<ul>
<% chapter.subchapters.each do |subchapter| %>
<li>
<%= subchapter.name %>
subchapter
<ul>
<% subchapter.checks.each do |check| %>
<li>
<%= check.name %>
check
<br>
<%= f.fields_for :check_results, check.check_results_for_form(@check_round.id) do |result| %>
<%= result.hidden_field(:check_id, :value => check.id) %>
<%= result.text_area(:observation, rows: 4, :id =>'obs' + check.id.to_s) %>
<% end %>
</li>
<% end %>
</ul>
</li>
<% end %>
</ul>
</li>
<% end %>
<ul>
<%= f.submit %>
<% end %>
{:action=>'update'})do | f |%>
-
章
-
分章
-
检查
支票(id)%>
“obs”+支票id.to_)%>
您的问题是重复显示检查结果的表单字段。查看视图代码的第7行:
<%= f.fields_for :check_results do |result| %>
<%= f.fields_for :check_results do |result| %>
<% if result.object.check == check %>
<%= result.hidden_field(:check_id, :value => check.id) %>
<%= result.text_area(:observation, rows: 4, :id =>'obs' + check.id.to_s) %>
<% end %>
<% end %>
<% end %>
您也可以独立于检查、子章节和章节的循环来循环检查结果,但我假设您希望保持UI的顺序和上下文。好的,从我看到的两件事情需要修复
首先,您的f.fields\u用于:检查结果do |结果|
需要一个额外的参数来指定它必须修改的检查结果。。。像这样的事情:
#helpers/check_rounds_helper.rb
def edit_or_instantiate_nested_check_results(f, check_round, check, new_check_result)
if check.check_results
f.fields_for :check_results, check_round.check_results.where(check_id: check.id) do |result|
result.hidden_field(:check_id, :value => check.id)
result.text_area(:observation, rows: 4, :id =>'obs' + check.id.to_s)
end #end for the already present check results
# if u want to add a new check result event if the check is populated
f.fields_for :check_results, new_check_result do |new|
new.hidden_field(:check_id, :value => check.id)
new.text_area(:observation, rows: 4, :id =>'obs' + check.id.to_s)
end #end for the new check result
else #if there is no existing check result nest a form for a new one
f.fields_for :check_results, new_check_result do |new|
new.hidden_field(:check_id, :value => check.id)
new.text_area(:observation, rows: 4, :id =>'obs' + check.id.to_s)
end #end for the new check result
end #end if statement
end
f.fields_for:check_results,@check_round.check_results.where(check_id:check.id)do|result
在完全相同的位置,因此check
变量指定正确的方式
2de,您需要在控制器中允许嵌套参数,以便在您提交时保存这些参数。通常,您应该在check\u round控制器中看到一个名为check\u round\u params
的方法。
这一个必须像这样才能让一切正常工作:
def check_round_params
params.require(:check_round_params).permit(
/*your needed params*/,
check_results_attributes: [:id, :check_id, :observation, /*all your nested params*/]
)
end
简而言之,您的更新
和创建
操作是根据那些允许的参数工作的,因此您需要在那里定义它们<代码>检查结果属性:
是rails理解这些参数用于嵌套模型的方式
以下是一些您可能会感兴趣的文档:这是我承诺的解决方案 既然您已经定义了必须拒绝使用空白观察值的检查结果,并且您的erb本身会涉及很多逻辑,我会将其全部放在一个辅助方法中,以便您的erb更干净。大概是这样的:
#helpers/check_rounds_helper.rb
def edit_or_instantiate_nested_check_results(f, check_round, check, new_check_result)
if check.check_results
f.fields_for :check_results, check_round.check_results.where(check_id: check.id) do |result|
result.hidden_field(:check_id, :value => check.id)
result.text_area(:observation, rows: 4, :id =>'obs' + check.id.to_s)
end #end for the already present check results
# if u want to add a new check result event if the check is populated
f.fields_for :check_results, new_check_result do |new|
new.hidden_field(:check_id, :value => check.id)
new.text_area(:observation, rows: 4, :id =>'obs' + check.id.to_s)
end #end for the new check result
else #if there is no existing check result nest a form for a new one
f.fields_for :check_results, new_check_result do |new|
new.hidden_field(:check_id, :value => check.id)
new.text_area(:observation, rows: 4, :id =>'obs' + check.id.to_s)
end #end for the new check result
end #end if statement
end
那么在你看来,
<%= form_for(@check_round, :url => {:action => 'update', :client_id => @client.id, :project_id => @project.id}) do |f| %>
<% @chapters.each do |chapter| %>
<%= chapter.name %>
<% chapter.subchapters.each do |subchapter| %>
<%= subchapter.name %>
<% subchapter.checks.each do |check| %>
<%= check.name %>
<% new_check_result = CheckResult.new(check_round_id: @check_round.id, check_id = check.id) %>
<%= edit_or_instantiate_nested_check_results(f, @check_round, check, new_check_result) %>
<% end %>
<% end %>
<% end %>
<% end %>
{:action=>'update',:client_id=>@client.id,:project_id=>@project.id})do | f |%>
应该是这样的;)。让我知道它是否成功:D
KR,您能显示创建时触发的日志吗?插入
检查轮数(项目id
,创建时,更新时)值(31,'2017-10-06 19:05:14','2017-10-06 19:05:14')插入检查结果(check\u round\u id
,check\u id
,correct
,观察
,风险
,创建时间
,更新时间
)值(179,1,'No',asdfadfa',Medio',2017-10-06 19:05:14',2017-10-06 19:05:14')插入检查结果
(check\u round\u id
,check\u id
,correct
,观察
,风险
,创建时间
,更新时间
)值(179,15,'No',asdfasdfas',Bajo 2017-10-06 19:05:14',2017-10-06 19:05:14')如果我在同一轮检查中填写两个检查,那么数据就是这样保存的。一轮检查,然后每次填写一个检查结果。@leogar07有没有对您有用的答案?如果有,请向上投票或接受。谢谢您好,谢谢您的回答。我没有把它放在这里,但我已经有嵌套的参数。您的解决方案只显示包含c的检查检查结果。我希望得到所有的检查结果,但是只有那些有检查结果的字段才填充,其余的字段应该是空的。再次感谢你的帮助!好的,我现在得到了你想要的结果…我今天晚些时候会编辑我的答案。简言之,我要做的是一个if check\u result语句。如果check.check\u result,然后修改e现有参数,如果为false初始化局部变量new_result=CheckResult.new…今天晚些时候会更清楚xD.U也应该编辑您的问题,这样我们就知道您的嵌套参数是正确的。我尝试了您的解决方案,得到了一个:“未定义的方法` where'for#”.Usuario相当于这个问题的检查结果。@GiovanniDiToro很抱歉回答得太晚……你找到问题的解决方案了吗?我想你可能在一个实例上使用了“where”方法……嗨,Patrick!一年多后我回来了,所以
#helpers/check_rounds_helper.rb
def edit_or_instantiate_nested_check_results(f, check_round, check, new_check_result)
if check.check_results
f.fields_for :check_results, check_round.check_results.where(check_id: check.id) do |result|
result.hidden_field(:check_id, :value => check.id)
result.text_area(:observation, rows: 4, :id =>'obs' + check.id.to_s)
end #end for the already present check results
# if u want to add a new check result event if the check is populated
f.fields_for :check_results, new_check_result do |new|
new.hidden_field(:check_id, :value => check.id)
new.text_area(:observation, rows: 4, :id =>'obs' + check.id.to_s)
end #end for the new check result
else #if there is no existing check result nest a form for a new one
f.fields_for :check_results, new_check_result do |new|
new.hidden_field(:check_id, :value => check.id)
new.text_area(:observation, rows: 4, :id =>'obs' + check.id.to_s)
end #end for the new check result
end #end if statement
end
<%= form_for(@check_round, :url => {:action => 'update', :client_id => @client.id, :project_id => @project.id}) do |f| %>
<% @chapters.each do |chapter| %>
<%= chapter.name %>
<% chapter.subchapters.each do |subchapter| %>
<%= subchapter.name %>
<% subchapter.checks.each do |check| %>
<%= check.name %>
<% new_check_result = CheckResult.new(check_round_id: @check_round.id, check_id = check.id) %>
<%= edit_or_instantiate_nested_check_results(f, @check_round, check, new_check_result) %>
<% end %>
<% end %>
<% end %>
<% end %>