0

我很难让它正确渲染和更新。发生了什么,我有一个多对多关联,关联连接表包含多个属性。一个案例可以有多个屏幕,一个屏幕可以有多个案例,并且可以为每个案例订购一个案例的屏幕。在我当前的设置中发生的另一个奇怪的项目是关联表在每次提交表单时都没有清除旧的关联值。新值被附加到表中。

课程:

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 我现在确信这里发生的问题是表格中缺少 case_screens_id。通常在清理期间,rails 将使用此 ID 清理以前的条目,然后填充新条目。因为我循环的是@screens,而不是当前存在的cases_screens(与案例相关联),所以如果没有查询每一行,我就无法获取id。

我想现在,我的解决方案是在 case_screens 中编写一个 before_save 方法,该方法将清理 case_screens 的当前条目,然后允许填充新值。

更新 1:15 我已经接近了至少一个项目,因此只有在选中复选框时才会插入记录。我已将更新的 :reject_if 添加到上面的 Case 类中。对于为什么只将值附加到表中以及为什么不删除以前的值,我仍然没有解决方案。

更新 4:00 我的最新尝试包括一个隐藏字段,其中包含 cases_screens ID(如果仅设置了记录)。这需要我在循环中进行子查询以获取当前的 case_screen_id。与 :reject_if 参数一起,现在可以正确更新值。但是,不能再删除当前设置的值。

我不可能做到这一点,感觉不像铁轨。这种情况是否是我应该在控制器中手动处理数据的情况之一?

4

1 回答 1

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 %>

这只会显示当前设置的案例/屏幕链接。用户将需要通过单独的屏幕将特定屏幕添加到案例中。

于 2012-12-09T18:30:19.713 回答