Multiple text field in one fields_for

2.1k views Asked by At

I'm building Project Management application and I'm creating Project with form_for but inside it I want a fields for to create 3 students.

I've set up my new.html.erb for Projects like this:

<h1>Creating new project</h1>

<%= form_for :project, url: projects_path do |f| %>
  <p>
    <%= f.label :name %>
    <%= f.text_field :name %>
  </p>

  <p>
    <%= f.label :lecturer %>
    <%= f.text_field :lecturer %>
  </p>

    <p>
        <%= f.fields_for :students do |s| %>
            <%= s.label :name %>
            <%= s.text_field :name %><br>
            <%= s.label :name %>
            <%= s.text_field :name %><br>
            <%= s.label :name %>
            <%= s.text_field :name %>
        <% end %>
    </p>

  <p>
    <%= f.submit %>
  </p>
<% end %>

And for the create method jusst added one simple line to see my form_for result:

  def create
    render text: params[:project].inspect
  end

So when I fill up the text fields on page and hit submit all I get is {"name"=>"asd", "lecturer"=>"ffff", "students"=>{"name"=>"qeew"}} so as you can see only my last student was passed to this dictionary.

How can I create multiple students in one fields_for? Or how can I set up these two models to work with each other. I hope you get my point of view and know what I want to achieve.

2

There are 2 answers

1
vee On BEST ANSWER

You could build the number of students you need to have fields for in your controller new action like follows:

# app/controllers/projects_controller.rb

def new
  @project = Project.new
  3.times do 
    student = @project.students.build
  end
end

This will build three students under project instance.

Then update your view's form_for declaration as follows:

# app/views/projects/new.html.erb

<%= form_for @project, url: projects_path do |f| %> 
  <p>
    <%= f.label :name %>
    <%= f.text_field :name %>
  </p>
  <p>
    <%= f.label :lecturer %>
    <%= f.text_field :lecturer %>
  </p>
  <p>
    <%= f.fields_for :students do |s| %>
      <%= s.label :name %>
      <%= s.text_field :name %>
    <% end %>
  </p>
  <p>
    <%= f.submit %>
  </p>
<% end %>
0
Bubbles On

Probably the easiest thing to do would be to pass in a proper Project object, instead of initializing it off of a symbol. Then, add three students to the object, and do a fields for the entire collection.

To do this, you'd want some code like this in projects#new -

@project = Project.new
3.times { @project << Student.new }

Then over in the form:

form_for @project do |f|
  ...
  f.fields_for :students do |s|
    s.label :name
    s.text_field :name
  end
end

The fields_for will automatically generate separate fields for each student that you added to the project in the controller.


One point I'm not entirely sure about: I think this will require you add a line accepts_nested_attibutes_for :students in your Project model, but I'm not quite sure. This does have the added advantage that you can create the students and the project quite easily in the create action in the controller, but isn't the right choice in every situation. If my solution does appear to require accepted_nested_attributes_for and you don't want it, let me know and I can update my answer with a similar, if more painful, solution.