Chris Baxter
Chris Baxter

Reputation: 1456

Update fails for nested attributes when nested object is ActiveRecord subclass

I have ActiveRecord with a subclass and its associated with another ActiveRecord object. I am able to create my object with nested attributes with a form with nested attributes no problem for a new object (following Ryan Bates rails cast - Thanks by the way :)). However when i do an update it fails to save the changes to either the main object or the related object when submitted

I have the following Activerecord classes and sub class.

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

And the sub class is

class BigRoom < Room

end

And the related class is

class RoomHeader < ActiveRecord::Base

  attr_accessible :key, :room_id, :value

  belongs_to :room
end

In my room controller I created the nested objects. note that i'm using :type to specify the subclass 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])
 ...

The form used for creating and editing is the same

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

And the _room_headers.html.erb partial is

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

To recap on the problem. I can successfully create a new BigRoom. In the new form when i create the BigRoom and I can successfully set values for the RoomHeader class and these are all saved successfully.

However when i Edit the the record and submit changes for update, nothing is saved. Either for changes for the Bigroom attributes or to the associated RoomHeader records.

Upvotes: 0

Views: 1304

Answers (2)

Chris Baxter
Chris Baxter

Reputation: 1456

Ok, nested attributes were a red herring. The problem is with STI

The Rails form helper guide says you can’t rely on record identification with STI.

In the form_for we need to coearce the ids to be the base type id otherwise the edit fails

so

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

should be

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

if you look at the difference in the html output

the problem html would create ids like big_room_fieldname when in edit mode when using .becomes we get ids like room_fieldname. in whihc case it saves and updates ok

Upvotes: 0

Aayush Khandelwal
Aayush Khandelwal

Reputation: 1071

first try by

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

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

if this works then their are some errors with your validdations

Upvotes: 0

Related Questions