How to use fields_for for child update in 1-to-many in rails 3.1.3?

A user has many user_levels and a user_level belongs to a user. We are having difficulty updating the user_level. Here is the code for user_level update:

    <%= simple_form_for @user do |f| %>       <% @user.user_levels.each do |level| %>         <%= f.fields_for :user_levels, level, :index => level do | builder> %>           <p><%= render :partial => 'user_levels', :locals => {:f => builder, :i_id => level.position} %></p>         <% end %>       <% end %>     <% end %>

The code above will display the current user_level with selected set to the current position. But the update was not saved for user_level.

Here is the user_levels partial

    <div class="fields">       <%= f.input :position, :collection => return_position, :prompt => "Choose position",                           :label => false, :include_blank => true, :selected => i_id %>       <%= link_to_remove_fields "remove", f %>     </div>

Here is the string posted to the server for params[:user]. There are currently two positions for the user and one gets deleted as update:

    {"name"=>"test eng", "login"=>"tester12", "password"=>"password", "password_confirmation"=>"password", "user_type"=>"employee", "user_levels_attributes"=>{"0"=>{"id"=>"5"}, "1"=>{"position"=>"elec_eng", "_destroy"=>"false", "id"=>"6"}}}

The app has no problem creating a new user with multiple user_levels.

Any solution for child update? Thanks so much

I recommend you visit Ryan Bates site RailsCasts.com and watch episodes 196 and 197. You should go ahead and subscribe, so he will keep doing stuff like this.

Cheers! SC

A user has many user_levels and a user_level belongs to a user. We are

having difficulty updating the user_level. Here is the code for

user_level update:

<%= simple_form_for @user do |f| %>

  <% @user.user_levels.each do |level| %>

    <%= f.fields_for :user_levels, level, :index => level do |

builder> %>

      <p><%= render :partial => 'user_levels', :locals => {:f =>

builder, :i_id => level.position} %>

    <% end %>

  <% end %>

<% end %>

The code above will display the current user_level with selected set

to the current position. But the update was not saved for user_level.

Here is the user_levels partial

<div class="fields">

  <%= f.input :position, :collection => return_position, :prompt

=> “Choose position”,

                      :label => false, :include_blank =>

true, :selected => i_id %>

  <%= link_to_remove_fields "remove", f %>

</div>

Here is the string posted to the server for params[:user]. There are

currently two positions for the user and one gets deleted as update:

{"name"=>"test eng", "login"=>"tester12", "password"=>"password",

“password_confirmation”=>“password”, “user_type”=>“employee”,

“user_levels_attributes”=>{“0”=>{“id”=>“5”},

“1”=>{“position”=>“elec_eng”, “_destroy”=>“false”, “id”=>“6”}}}

The app has no problem creating a new user with multiple user_levels.

Any solution for child update? Thanks so much

Strange. The params hash seems correct (I did some similar tests in my app). If I understand correctly, this should do:

  • leave the user_level with id 5 untouched

  • update the position of user_level with id 6 (if it was changed)

The “_destroy”=>“false” should not matter

Which one of the two user_levels gets deleted (with id 5 or id 6).

If you puts the user.user_levels (in the controller) just before the

update_attributes line, like below, you can make sure the user_levels are still there just before.

def update

add this to debug the status just before the update_attributes

puts user.user_levels.inspect

user.update_attributes(params[:user]) … end

Also, you could try the update_attributes action in the rails console to isolate the problem.

user = User.find … user.user_levels

h = {“name”=>“test eng”, “login”=>“tester12”, “password”=>“password”,

“password_confirmation”=>“password”, “user_type”=>“employee”,

“user_levels_attributes”=>{“0”=>{“id”=>“5”},

“1”=>{“position”=>“elec_eng”, “_destroy”=>“false”, “id”=>“6”}}}

user.update_attributes(h) user.user_levels

That is how tested the expected behavior (of course with different model

names for my app).

HTH,

Peter