【问题标题】:Update fails for nested attributes when nested object is ActiveRecord subclass当嵌套对象是 ActiveRecord 子类时,嵌套属性更新失败
【发布时间】:2012-10-26 18:51:53
【问题描述】:

我有一个带有子类的 ActiveRecord,并且它与另一个 ActiveRecord 对象相关联。 我可以使用具有嵌套属性的表单创建具有嵌套属性的对象,这对于新对象没有问题(遵循 Ryan Bates rails cast - 顺便感谢 :))。但是,当我进行更新时,提交时无法将更改保存到主对象或相关对象

我有以下 Activerecord 类和子类。

class Room < ActiveRecord::Base

 attr_accessible :name, :type, room_headers_attributes

 has_many :room_headers, dependent: :destroy

 accepts_nested_attributes_for :room_headers , :allow_destroy => true

end

而子类是

class BigRoom < Room

end

而相关的类是

class RoomHeader < ActiveRecord::Base

  attr_accessible :key, :room_id, :value

  belongs_to :room
end

在我的房间控制器中,我创建了嵌套对象。请注意,我使用 :type 来指定子类类型

def new
    @room = current_user.passes.build(params[:room])
    @room.type = params[:type]    

    3.times do
        room_header = @room.room_headers.build
      end

    ....
 end

 ....

def edit
  @room = Room.find(params[:id])
end

def update
    @room = Room.find(params[:id])

 if @room.update_attributes(params[:room])
 ...

用于创建和编辑的表单是一样的

<%= form_for(@room) do |f| %>

<div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name %>
</div>

<%= f.fields_for :room_headers do |builder| %>
   <%= render 'room_header_fields', f: builder %>
<% end %>

<div class="actions">

    <%= f.submit %>
  </div> 

<% end &>

而 _room_headers.html.erb 部分是

<p class="fields">
  <%= f.label :key, "Key" %>
  <%= f.text_field :key %>
  <%= f.label :value, "Value" %>
  <%= f.text_field :value %>
  <%= f.check_box :_destroy %>
  <%= f.label :_destroy, "Remove Header" %>
</p>

回顾一下这个问题。我可以成功创建一个新的 BigRoom。在我创建 BigRoom 的新表单中,我可以成功设置 RoomHeader 类的值,并且这些值都已成功保存。

但是,当我编辑记录并提交更改以进行更新时,没有保存任何内容。用于 Bigroom 属性或关联 RoomHeader 记录的更改。

【问题讨论】:

    标签: ruby-on-rails activerecord subclass nested-attributes


    【解决方案1】:

    第一次尝试

      if @room.update_attribute(params[:room])
    
         rather
       if @room.update_attributes(params[:room])
    

    如果这可行,那么他们的验证有一些错误

    【讨论】:

    • 我不确定我是否理解您的建议?
    • update_attribute 不验证它只是保存它的记录,而 update_attributes 首先验证然后保存。所以我问你检查是否是由于验证而没有保存的东西
    • 我在 update_attributes 之后添加了一条评论,看起来很成功。但数据没有保存,存储到数据库中。当我查看日志时,对于父对象或嵌套对象,我也没有看到任何 SQL 更新调用
    【解决方案2】:

    好的,嵌套属性是一个红鲱鱼。问题在于性传播感染

    Rails 表单助手指南说您不能依赖 STI 的记录识别。

    在 form_for 中,我们需要将 id 强制为基本类型 id,否则编辑会失败

    所以

    <%= form_for(@room) do |f| %>
    

    应该是

    <%= form_for(@room.becomes(Room) do |f| %>
    

    如果您查看 html 输出的差异

    问题 html 在编辑模式下会创建像 big_room_fieldname 这样的 id 当使用 .becomes 时,我们会得到像 room_fieldname 这样的 id。在这种情况下,它可以保存和更新

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-25
      相关资源
      最近更新 更多