6

When I run the rails server and go to the school/new page on my site, the field with the label "school" where I can enter the school's name appears, but all the other fields under fields_for which are for entering the school administrator's info do not show up on my site -- when I use "inspect element" on my form it is like they are not even there. Why aren't they appearing on my page?

<%= form_for(@school) do |f| %>
  <% if @school.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@school.errors.count, "error") %> prohibited this school from being saved:</h2>

      <ul>
      <% @school.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :school %><br />
    <%= f.text_field :name %>
  </div>
  <%= f.fields_for :admin do |f2| %>
    <div class="field">
      <%= f2.label "administrator name" %><br />
      <%= f2.text_field :name %>
    </div>
    <div class="field">
      <%= f2.label "administrator email" %><br />
      <%= f2.text_field :email %>
    </div>
    <div class="field">
      <%= f2.label "administrator gender" %><br />
      <%= f2.text_field :gender %>
    </div>
  <% end %>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

2 Answers 2

22

TLDR:

For my purposes, I had to make sure the form object's child association was populated with a new record. Originally, the parent object's child association returned nil. I just had to instantiate an object and the form rendered correctly.


In case anyone arrives here from Google, I had a the same problem as the poster, but the accepted answer didn't help me.

First, some background. When you use the plain fields_for instead of f.fields_for, the fields are rendered differently. The plain version (as suggested above) does not associate the fields rendered with the form's object. Look at the different outputs:

fields_for

form_for @parent_instance do |f|
  f.text_field :parent_field
  fields_for :child_obj do |child_fields|
    child_fields.text_field :child_field
  end
end

Renders

<input id="parent_class_parent_field" name="parent_class[parent_field]" type="text" />
<input id="child_class_child_field" name="child_class[child_field]" type="text" />

Which Rails will parse into these parameters:

{ "parent_class" => {
      "parent_field" => "Parent field value"
    },
  "child_class" => {
      "child_field" => "Child field value"
    }
}

f.fields_for

form_for @parent_instance do |f|
  f.text_field :parent_field
  f.fields_for :child_obj do |child_fields|
    child_fields.text_field :child_field
  end
end

Renders

<input id="parent_class_parent_field" name="parent_class[parent_field]" type="text" />
<input id="parent_class_child_class_child_field" name="parent_class[child_class][child_field]" type="text" />

Which Rails will parse into these parameters:

{ "parent_class" => {
      "parent_field" => "Parent field value",
      "child_class" => {
          "child_field" => "Child field value"
        }
    }
}

The difference is that the child object's parameters only get nested under the parent when you use f.fields_for. So using the accepted answer's suggestion of using the bare fields_for didn't work for creating an associated record.

Turned out, the reason f.fields_for wasn't rendering anything was because the child association was nil. To fix it and have my form render correctly and return the parameters in the properly nested way, I had to instantiate that association like this in my controller:

def new
  @parent = ParentClass.new
  @parent.child_obj = ChildClass.new
end
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, this helped a lot. Sometimes though, it will not be practical to instantiate the object. In those cases, it is possible to supply the object to the fields for command like f.fields_for :child, child_instance
Perhaps you could add what to do when the child association is a has_many relationship.
+1 on the suggestion. Great answer, but still confused on what to do when the association is has_many since it will be multiple child objects instead of one.
18
 <%= f.fields_for :admin do |f2| %>

try removing the f.

try with just this:

<%= fields_for :admin do |f2| %>

There is two way to use field_for:

A generic one. (like my example).

A nested one.

To use the nested field_for (f.field_for), your model object must be setup correctly

Ex: Relation with @school and @admin

class School< ActiveRecord::Base
  has_one :admin
  accepts_nested_attributes_for :admin
end

In the end, there is multiple ways of using field_for depending on how you setup the relations on your model object.

This guide explain in details all the possible setup. You might find why it was not working for you.

My bet is your Admin and School model object are not in a relation, or you didn't put the accepts_nested_attributes_for :admin in your School object.

5 Comments

f represents @school elements . fields_for is used alone and you may pass :something or "@something". I don't know what guide you read, but i recommend the API doc of RoR on theire website. There is often good code sample. Have fun
In this post they use "f.fields_for" -> stackoverflow.com/questions/2613576/…. Can you explain it here?
Here too they use the dot before the fields_for: stackoverflow.com/questions/2249160/…. Please explain.
@Kvass Sorry you are right, my comment was talking about the generic use.. but there is other way to use it .. see my edit in the response
Using plain fields_for isn't the same as using f.fields_for. You don't get the nested parameters as you probably want. To fix it, I had to instantiate a new record for the association, instead of having the association be nil. See my answer below

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.