我在使用表单管理 has_many :through 关联时遇到问题。我不想做的是编辑关联模型的属性,其中存在大量信息,相反,我只想管理关联。我知道我可以通过操纵传递给我的操作的表单参数并手动构建关系来做到这一点,但如果可能的话,我更愿意采用 Rails 方式。
关于我的案例的一件有趣的事情是,这个 has_many :through 关联实际上是在我已经使用accepts_nested_attributes_for保存的模型上
以下是我的模型:目标、里程碑和计划。
class Goal < ActiveRecord::Base
has_many :milestones, inverse_of: :goal, dependent: :destroy
accepts_nested_attributes_for :milestones, :allow_destroy => true
end
class Milestone < ActiveRecord::Base
belongs_to :goal, inverse_of: :milestones
has_many :milestone_programs
has_many :programs, :through => :milestone_programs
end
class Program < ActiveRecord::Base
end
现在,在我的目标编辑视图中,我需要能够添加和删除里程碑,对于这些里程碑,我需要能够添加和删除计划关联。这是我的表单的代码。
<%= form_for @goal do |f| %>
<%= f.fields_for :milestones do |f_milestone| %>
<%= f.hidden_field :id, :value => f.object.id %>
<%= f.hidden_field :name, :value => f.object.name %>
<a href="javascript:void(0)" class="milestone-remove">- remove</a>
<ul>
<%= f.fields_for :programs do |f_prog| %>
<li>
<%= f_prog.object.name %>
<a href="javascript:void(0)" class="program-remove">- remove</a>
</li>
<% end %>
</ul>
<% end %>
<%= f.submit 'Save' %>
<% end %>
在我的控制器中,我有
class GoalsController < ApplicationController
# PATCH/PUT /goals/:id
def update
if @goal.update(goal_params)
redirect_to @goal
end
end
def goal_params
params.require(:goal).permit(:name, :milestones_attributes => [ :id, :name, :_destroy ])
end
end
这个表单需要像一个工作表,您可以在其中进行更改,并且只有在最后单击“保存”后才保存更改,所以我不相信像 cocoon 或nested_forms 这样的宝石会有帮助。
到目前为止,我的代码可以完美地管理与我的目标相关的里程碑及其属性。但现在我希望能够管理与这些里程碑相关的计划列表。
我尝试过使用 Accepts_nested_attributes_for 但这并不完全是我想要的,因为我不关心编辑模型的嵌套属性,程序属性将保持静态。
我想我可能可以在每个程序的表单中使用类似的内容来建立关联:
<input type="hidden" name="goal[milestones_attributes][1][program_ids][1]" >
但这也不起作用(当然我已经将 :program_ids 添加到我的白名单参数中)。我需要将 Magic Rails 方法添加到我的控制器中吗?
我在这里缺少什么?
提前致谢!