提问人:turzmobine 提问时间:2/16/2022 更新时间:2/17/2022 访问量:28
添加嵌套表单时提交表单的 Rails 问题
Rails Issue with submitting form when adding nested form
问:
这里是 Rails 新手。我相信我对fields_for如何在轨道形式中运作感到困惑。我与中间的项目、组织和附属机构建立了许多关系。一个项目可以有多个组织,一个组织可以有多个项目。隶属关系位于中间,带有一个 :role 属性,用于编辑该属性以显示组织在项目中扮演的角色。我能够很好地将许多组织添加到项目中。我利用 chosen-rails 实现了一个简洁的 UI 来选择多个、搜索等。我可以很好地将组织添加到项目中。但是,在尝试通过使用fields_for表单更改角色属性来实施某种方法来操纵每个组织在项目中扮演的角色时,原始表单的提交会中断。我尝试了许多fields_form变体,包括来自此处指南的变体。
在 project.rb 中:
def affiliations_attributes=(affiliations_attributes)
affiliations_attributes.each do |i, affiliation_attributes|
if affiliation_attributes[:role].length > 0
self.affiliations.build(affiliation_attributes)
end
end
end
在项目表单中:
<%= f.fields_for :affiliations do |affiliation_builder|%>
<%= affiliation_builder.label :role %>
<%= affiliation_builder.text_field :role %>
<% end %>
使用此设置,在提交表单时,我收到一条错误消息,指出“隶属关系组织必须存在”。我不明白为什么,因为我甚至没有在这里编辑隶属关系或组织。我错过了什么吗?
在此之前,我尝试为fields_for表单执行此操作:
<%= f.fields_for :affiliations do |affiliation|%>
<%= affiliation.label :role, ("Role in Project") %>
<%= affiliation.text_field :role, autofocus: true, autocomplete: 'off', placeholder: 'e.g. Donor, Founder', class: 'form-control' %>
<% end %>
项目总监:
def project_params
params.require(:project).permit(:organization, {organization_ids: []},
:stream_name, :implementation_date, :narrative,
:length, :primary_contact,:number_of_structures, :structure_description,
:name, affiliations_attributes: [:id, :role], photos: [])
end
现在,令人惊讶的是,这在更新隶属关系中的角色属性时有效。我还可以毫无问题地将组织添加到项目中,并将后续角色添加到创建的隶属关系中。但是,当我尝试删除组织时,问题出现了。Rails 在 ProjectsController#update 中闪烁 ActiveRecord::RecordNotFound 错误,指出“找不到 ID= 的 ID= 项目的隶属关系”。我不知道这里发生了什么,几天来我一直在用头撞墙,试图解决这个问题。我唯一能想到的是,不知何故存在 ID 匹配问题,或者某些参数未正确传递。在玩弄上述第二种方法的project_params并从affiliations_attributes中删除 :id 时,我确实注意到的一件事是,我闪烁了关于需要“隶属关系组织”的相同错误消息。也许有某种方法可以使用 affiliation_builder 方法传递组织 ID?在这里,任何帮助或指导将不胜感激。谢谢。
class Affiliation < ApplicationRecord
belongs_to :project
belongs_to :organization
end
class Organization < ApplicationRecord
has_many :affiliations
has_many :projects, through: :affiliations
end
class Project < ApplicationRecord
has_many :affiliations
has_many :organizations, through: :affiliations
accepts_nested_attributes_for :affiliations
def affiliations_attributes=(affiliations_attributes)
affiliations_attributes.each do |i, affiliation_attributes|
if affiliation_attributes[:role].length > 0
self.affiliations.build(affiliation_attributes)
end
end
end
end
答:
为什么 |i, affiliation_attributes| ? 使用 |affiliation_attributes|
评论
我相信我已经找到了解决方案,尽管我不确定它在技术上是否正确。我查看了更新 Project 时推送属性的顺序,我注意到organization_ids在 affiliations_attributes 之前在 Hash 中被推送。所以我认为它试图更新一些不存在的东西,并提供一些误导性的信息(至少对我来说是这样)。我能够通过强制首先在单独的更新中推送affiliations_attributes,然后在主更新中推送其余的项目属性来解决这个问题。
def project_organization_params
params.require(:project).permit(:id, {affiliations_attributes: [:id,
:role]})
end
然后更新:
@project = Project.find(params[:id])
@project.update(project_organization_params)
if @project.update(project_params)
...
现在一切似乎都很好。
评论