Rails — fields_for not working?

2020-06-22 01:49发布

问题:

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 %>

回答1:

 <%= 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.



回答2:

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