views:

39

answers:

1

Hi I have a form with nested attributes that I need to place on many different pages. Not necessarily the model it belongs to. So I have this form on the battalions show page. The user information is created just fine, but the user has_many roles and these attributes are not being created. I have many other nested forms that work just fine, I can't quite figure out what I am missing to make this work.

class User < ActiveRecord::Base  
  has_many :roles   
  accepts_nested_attributes_for :roles, :allow_destroy => true

      def active?
  active
end

def activate!(params)
  self.active = 1
  self.login = params[:user][:login]
  self.password = params[:user][:password]
  self.password_confirmation = params[:user][:password_confirmation]
  save
end

def deliver_activation_instructions!
    reset_perishable_token!
    NotifierMailer.deliver_activation_instructions(self)
end

def deliver_activation_confirmation!
    reset_perishable_token!
    NotifierMailer.deliver_activation_confirmation(self)
end

def has_no_credentials?
    self.crypted_password.blank?
end

def signup!(params)
    self.login = params[:user][:login]
    self.email = params[:user][:email]
    self.name = params[:user][:name]
    self.position = params[:user][:position]
    self.battalion_id = params[:user][:battalion_id]
    self.company_id = params[:user][:company_id]
    self.platoon_id = params[:user][:platoon_id]

    save_without_session_maintenance
end
end 

class Role < ActiveRecord::Base  
  belongs_to :user  
end  


<% form_for :user, @user, :url => users_path do |f| %>
        <%= f.error_messages %>
      <% f.fields_for :roles do |f| %>
        <%= render :partial => "role", :locals => { :f => f, :role => 'battalion'} %>
      <% end %>
        <%= render :partial => "form", :locals => { :f => f, :position => 'Battalion Commander', :company => 'nil'} %>
      <%= f.submit "Register" %>
    <% end %>

_role.html.erb

<%= f.hidden_field(:name, :value => role) %>

_form.html.erb

<%= f.hidden_field(:position, :value => position) %>
<%= f.hidden_field(:battalion_id, :value => @battalion.id) %>
<%= f.hidden_field(:company_id, :value => company) %>

<%= f.label(:name, "Name:") %>
<%= f.text_field :name%>
<br />
<%= f.label(:email, "E-Mail:") %>
<%= f.text_field :email%>
<br />

This is what happens when I create the user:

Processing UsersController#create (for 127.0.0.1 at 2010-02-14 22:15:16) [POST] Parameters: {"user"=>{"name"=>"Chirs", "roles"=>{"name"=>"battalion"}, "company_id"=>"nil", "position"=>"Battalion Commander", "email"=>"[email protected]", "battalion_id"=>"1"}, "commit"=>"Register", "action"=>"create", "authenticity_token"=>"PcGbsQNG7wKKPDZTM+JGry/a1aBWZuoyaCNwlqlCJ0g=", "controller"=>"users"}

I just does not trigger the create action for roles.

It seems like this should be pretty simple, my only guess is having it moved away from the users model is creating the issue. Should it be form_for @battalions and then make User nested and Role nested, that is three levels and just doesn't seem right.

Any help would be greatly appreciated.

A: 

When dealing with accepts_nested_attributes_for you need to assign to "#{association}_attributes". In your case you want roles_attributes.

fields_for when used in conjunction with accepts_nested_attributes_for should generate the correct HTML.

Your views/partials appear to be correct, but your hidden field isn't generating the correct input id.

The only way I've been able to reproduce your problem is when @user is nil. Is there any chance you're forgetting to initialize a user before using this form. It's not a hard thing to overlook when using the same partial on multiple pages.

Just insure you do @user = User.new in all the controller actions that render this form.

EmFi
Thanks for your help. I have accepts_nested_attributes_for :roles, :allow_destroy => true in the user model, is that not enough? Seems that it is in other nested forms in the app. Where would I need to assign "#{association}_attributes"? I don't think the problem is with the user because I create the user just fine, just not the associated role. Even when I try and do this straight from the User model I have the same issue. I am using Authlogic to create my new Users, I am wondering if it could have anything to do with that? Appreciate you looking at it.
looloobs
One more thing: When I create a new User this is what happens and I not sure why this "roles"=>"#<Role:0x19751ac>" is in there?Processing UsersController#create (for 127.0.0.1 at 2010-02-15 15:30:52) [POST] Parameters: {"user"=>{"name"=>"John Jones", "roles"=>"#<Role:0x19751ac>", "roles_attributes"=>{"0"=>{"name"=>"battalion"}}, "company_id"=>"", "login"=>"jjones2", "platoon_id"=>"", "position"=>"", "email"=>"[email protected]", "battalion_id"=>""}, "commit"=>"Register", "action"=>"create", "authenticity_token"=>"PcGbsQNG7wKKPDZTM+JGry/a1aBWZuoyaCNwlqlCJ0g=", "controller"=>"users"}
looloobs
Any time you create or update a user and intend to modify the associated roles directly you would assign to roles_attributes. When you use accepts_nested_attributes_for, this is done automatically for you when you use fields_for. You will see it in the input names if you check the source of the rendered views.
EmFi
Unless you've changed something in your views, I have no idea why you have an extra roles attribute on user.
EmFi
Thanks for your help, I was missing this @user = User.new(params[:user]) in my controller, instead I had @user = User.new
looloobs