Craig McGuff
Craig McGuff

Reputation: 3978

How do I use nested attributes with the devise model

I have the same issue as Creating an additional related model with Devise (which has no answer).

I have overridden the devise view for creating a new user and added a company name, I have changed the model to use accepts_nested_attributes_for

There are no errors, but it is not adding the nested record and I don't have a controller where I can modify the request.

I have the following (shortened to make it readable):

routes.rb

map.devise_for :users
map.resources :users, :has_many => :companies

user.rb

has_many :companies
accepts_nested_attributes_for :companies
devise :registerable ... etc

company.rb

belongs_to :user

new.html.erb

...
<% form_for resource_name, resource, :url => registration_path(resource_name) do |f| %>
...
  <% f.fields_for :company do |company_form| %>
    <p><%= company_form.label :name %></p>
    <p><%= company_form.text_field :name %></p>
  <% end %>
...

UPDATE: I didn't add :company to the attr_accessible list in the User model.

Upvotes: 11

Views: 15444

Answers (3)

Ivan Prasol
Ivan Prasol

Reputation: 303

You can add the following method to the User model:

user.rb

def with_company
  self.companies.build
  self
end

And modify the view:

new.html.erb

...
<% form_for [resource_name, resource.with_company], :url => registration_path(resource_name) do |f| %>
...
  <% f.fields_for :company do |company_form| %>
  ...
  <% end %>

This way, you'll have the nested form to add one company to the user. To dynamically add multiple companies to the user, check the Railcast #197 by Ryan Bates. Make sure you are passing the pair of resources as an array, otherwide you will get an error like this: "wrong number of arguments (3 for 2)".

Upvotes: 16

Atarang
Atarang

Reputation: 422

I realised this is a very old thread, but since I found a better solution, hence the reply.

Just change the new.html.erb as follows,

<% form_for(resource, :as => resource_name,:url => registration_path(resource_name) do |f| %>
    ...
    <% prefix = "user[company_attributes]"%>
    <% fields_for prefix, @user.company do |company_form| %>
    ...
    <% end %>
<% end %>

This way when @user.save gets invoked, it would run company.save too with all the validations you may have in company model.

I don't have whole lot of RoR experience, but I think this is a better solution. What do you think?

Upvotes: 0

Preston Marshall
Preston Marshall

Reputation: 1195

You may be trying to mass assign some protected variable, OR you might not be saving a valid record. Check to make sure that the record is actually saving to the db.

Upvotes: 2

Related Questions