25

I have a user and a profile model. One user can have many profiles. I need to access only one information from the profiles section (viz the phone number) in my user model during the user creation process. Hence I'm trying to get it done through attr_accessible. My user.rb looks like this.

has_many :profiles
attr_accessible :handle, :email, :password, :profile_mobile_number
attr_accessor : :profile_mobile_number

The problem that I'm facing is that when I try to call the getter method profile_mobile_number in a method in user.rb (the method is private, though I think it doesn't matter), I'm getting a null value. I use the following in my users/new.html.erb form

My question is what is the right way to do this? Should I use <% f.fields_for :profile do |ff| -%> or <% f.fields_for :profiles do |ff| -%> (notice that the second one is plural). When I use the plural :profiles, I don't even see the fields on the form. What am I missing here? And what is the tense that needs to be used in model user.rb? :profile_phone_number or :profiles_phone_number? Thanks.

Puce
  • 978
  • 14
  • 27
Swamy g
  • 2,016
  • 4
  • 23
  • 35
  • Like I said I was using f.fields_for :profiles and the fields in the form weren't showing up. Turns out that I had to add @user.profiles.build in the controller. But now I'm not able to have both attr_accessible and accepts_nested_attributes_for in user.rb. The former overrides the latter. But I do want to have attr_accesible for the attributes of the user model while NOT restricting access to the attributes of the profile model. Any ideas? Thanks. – Swamy g Feb 13 '10 at 18:00

4 Answers4

21

You could do something like the following:

<% form_for @user, :url => { :action => "update" } do |user_form| %>
  ...
  <% user_form.fields_for :profiles do |profiles_fields| %>
     Phone Number: <%= profiles_fields.text_field :profile_mobile_number %>
   <% end %>
<% end %>

But since you already have an association, then might as well use 'accepts_nested_attributes_for'

Pran
  • 3,101
  • 2
  • 20
  • 26
  • 6
    It's worth mentioning that this iterates over the associated objects that already exist. It does however create no new empty record to be filled. Use a helper for that which appends a new record if none is in the association, eg "def setup_profiles(user); user.profiles.build if user.profiles.blank? || !user.profiles.map(&:new_record?).any?; user; end", then using "form_for setup_profiles(@user) do ..." – hurikhan77 Feb 13 '10 at 14:50
  • 1
    @hurikhan77's comment is crucial! You need to build a new object if no associated objects exist, otherwise nothing shows up in your form! – agmin Oct 17 '12 at 20:04
13

You should watch RailsCasts Nested Model Form.
thanks Ryan Bates great work.

allenwei
  • 3,799
  • 3
  • 21
  • 25
3

http://apidock.com/rails/v3.2.8/ActionView/Helpers/FormHelper/fields_for

This api dock link list many Nested Attributes Examples including one-to-one, one-to-many. It's very helpful!

ryancheung
  • 2,695
  • 3
  • 19
  • 24
0

You can use 'accepts_nested_attributes_for' to do this; but there's a little trick in forms:

You must use the singular, and call fields_for for each profile, like this:

<% form_for @user do |f| -%>
<% @user.profiles.each do %>
<% f.fields_for :profile_attributes, profile do |ff| -%>
<% end %>

Notice that is :profile_attributes, instead of just :profile.

nanda
  • 1,293
  • 9
  • 16
  • 3
    If is a *belongs_to polymorphic* association, you have to define a *build_profile* method in your User model. – nanda Feb 12 '10 at 13:40