我正在努力让它正确渲染和更新。发生了什么,是我有多对多关联,关联连接包含多个属性的表。一个箱子可以有很多屏幕,一个屏幕很多箱子,并且可以为每个箱子订购一个箱子的屏幕。我当前设置中发生的另一个奇怪的项目是,每次提交表单时,关联表都没有清除旧的关联值。新值将附加到表中。
类:
class Case < ActiveRecord::Base
attr_accessible :cases_screens_attributes
has_many :cases_screens
has_many :screens, :through => :cases_screens
accepts_nested_attributes_for :cases_screens,
:allow_destroy => true,
:reject_if => lambda { |p| p[:screen_id].nil? }
end
class Screen < ActiveRecord::Base
has_many :cases_screens
has_many :cases, :through => :cases_screens
end
class CasesScreen < ActiveRecord::Base
attr_accessible :order
belongs_to :case
belongs_to :screen
end
控制器:
# GET /cases/1/edit
def edit
@case = Case.find(params[:id])
@cases_screens = @case.cases_screens.order("cases_screens.[order] ASC")
@screens = Screen.where({:active => true})
end
# PUT /cases/1
# PUT /cases/1.json
def update
@case = Case.find(params[:id])
@cases_screens = @case.cases_screens.order("cases_screens.[order] ASC")
@screens = Screen.where({:active => true})
respond_to do |format|
if @case.update_attributes(params[:case])
format.html { redirect_to case_path(@case), :notice => t(:case_successfully_updated) }
format.json { head :no_content }
else
format.html { render :action => "edit" }
format.json { render :json => @case.errors, :status => :unprocessable_entity }
end
end
end
我尝试过多次尝试使用fields_for无济于事。这是我目前在_form.erb.html文件中的内容。最终目标是在案例表格中查看所有屏幕的列表,每个屏幕旁边都有一个复选框。每个复选框还具有“订单”的关联输入。提交后,将正确填充cases_screens表(如果不再选择旧值,则删除旧值)。
<div class="controls">
<% @screens.each do |s| %>
<label>
<%= check_box_tag("case[cases_screens_attributes][#{s.id}][screen_id]", s.id, @case.screen_ids.include?(s.id)) %>
<%= s.name %>
</label>
<%= select_tag("case[cases_screens_attributes][#{s.id}][order]", options_for_select(1..@screens.size, 2)) %>
<% end %>
</div>
我现在已经在这个墙上撞了几天我的头,我似乎无法做到这一点。任何帮助将非常感谢。
附加说明:
我使用简单的表单,我只是做了以下内容:
<%= f.association :screens %>
并且一切都按预期工作(没有订单属性更新)。关联表已正确清理。当然,这是指向嵌套属性的方向作为罪魁祸首,但我不确定。
周三10:45更新 我现在确信这里发生的问题是没有在表单中出现cases_screens_id。通常在清理期间,rails将使用此ID清除以前的条目,然后填充新的。由于我循环遍历@screens,而不是当前存在的cases_screens(与案例相关联),我无法获取id而不会查询每一行。
我想现在,我的解决方案是将before_save方法编写到cases_screens中,这将清除cases_screens的当前条目,然后允许填充新值。
更新1:15 我至少与其中一个项目进行了一点距离,以便仅在选中复选框时才插入记录。我已将更新的:reject_if添加到上面的Case类中。我仍然没有解决为什么值只附加到表,以及为什么不删除以前的值。
更新4:00 我的最新尝试包括一个隐藏字段,如果仅设置了记录,则该字段包含cases_screens ID。这需要我在循环中创建子查询以获取当前的cases_screen_id。除了:reject_if参数之外,现在正在更新值。但是,无法再删除当前设置的值。
我无法做到这一点,它感觉不像铁轨。这个场景是我应该在控制器中手动处理数据的那个场景吗?
答案 0 :(得分:0)
此时,我正在将此问题归结为设计问题。
我现在正在使用
<% @case.cases_screens.each do |cs| %>
<%= hidden_field_tag("case[cases_screens_attributes][#{cs.id}][id]", cs.id) %>
<%= hidden_field_tag("case[cases_screens_attributes][#{cs.id}][screen_id]", cs.screen_id) %>
<%= hidden_field_tag("case[cases_screens_attributes][#{cs.id}][_destroy]", 1) %>
<label><%= check_box_tag("case[cases_screens_attributes][#{cs.id}][_destroy]", 0, @case.cases_screen_ids.include?(cs.id)) %> <%= cs.screen.name %></label>
<%= text_field_tag("case[cases_screens_attributes][#{cs.id}][ordinality]", cs.ordinality) %>
<% end %>
这会导致仅显示当前设置的大小写/屏幕链接。用户需要通过单独的屏幕将特定屏幕添加到案例中。