Search code examples
ruby-on-railsrubyrails-activerecordhas-manybelongs-to

Rails: belongs_to association through a form not populating


I'm working on the controller for my class, Project. It has a belongs_to relationship with Client.

I'm not sure why this is happening, but when I create a new project through the form, it has a name assigned to it, but no fee and no client_id.

Here's the relevant code:

Project controller

class ProjectsController < ApplicationController

  def index
  end

  def show
  end

  def new
    @project = Project.new 
  end

  def edit
  end

  def create
    @project = Project.new(project_params)
    if @project.save
      redirect_to projects_url
    else
      render 'new'
    end
  end

  def update
  end

  def destroy
  end

  private 

  def project_params
    params.require(:project).permit(:name, :feee, :client_id)
  end
end

projects/new view

<div id="newproject-form">
    <h1>Create a project</h1>
    <%= form_for @project do |p| %>
        <div id="newproject-form-input">
            <ul>
                <li><%= p.label :name, "Project name: " %><br>
                <%= p.text_field :name, size: 40 %></li>

                <li><%= p.label :fee, "Fee: " %><br>
                <%= p.text_field :fee %></li>

                <li><%= p.label :client, "Client name: " %><br>
                <%= collection_select(:client_id, :name, current_user.clients, :id, :name) %></li>

                <li><%= p.submit "Create project", class: "form-button" %>, or <%= link_to "Cancel", 
                root_path %></li>
            </ul>
        </div>
    <% end %>
</div>

Project model

class Project < ActiveRecord::Base
  belongs_to :client

end

Solution

  • You have to call collection_select on the form builder:

    # change this
    <%= collection_select(:client_id, :name, current_user.clients, :id, :name) %>
    # to this
    <%= p.collection_select(:client_id, current_user.clients, :id, :name) %>
    

    By using the FormBuilder p you are telling the collection_select that you are editing a Project object (see p.object to return the object of the form builder).


    If you look at the collection_select documentation (http://apidock.com/rails/ActionView/Helpers/FormOptionsHelper/collection_select):

    collection_select(object, method, collection, value_method, text_method, options = {}, html_options = {})

    If you call collection_select by its own (not from a form builder, provided by the form_for method), you have to give as first argument the object's name. In your case, it would have been collection_select(:project, :client_id, #etc.) to generate params like params[:project][:client_id].