Topic: Multiple Models in One Form: How to create the parent?

Hi there

I'm trying to create a page that allows users to create an account. In the same form, I want users to say which department they work for.

The departments all pre-exist, so the form doesn't need to create a new department: just say which (existing) department they work for.

I'm using form_for for my @user and field_for for its parent department but I can't get it to work.

The error message I'm getting is:

ActiveRecord::RecordNotFound in UsersController#create

Couldn't find OrganisationUnit without an ID

The form parameters are:

{"user"=>{"password_confirmation"=>"primera",
"username"=>"bloggj",
"first_name"=>"Joe",
"last_name"=>"Bloggs",
"password"=>"primera"},
"commit"=>"Add User",
"authenticity_token"=>"HOUXDWnmLOfPzEutkNrUEgvbC3qHBeHqqbVgESUgPNo=",
"nil_class"=>{"organisation_unit"=>"20"}}

I can't work out why Rails is creating 'nil_class' in my view.


I've created associations in my models:

class User < ActiveRecord::Base

  belongs_to :organisation_unit

<end>

class OrganisationUnit < ActiveRecord::Base
  
  has_many :users

<end>

I've added an 'organisation_unit_id' foreign key to my users table

The following is taken from my users controller:

class UsersController < ApplicationController

  . . .

    # GET /users/new
    # GET /users/new.xml
    def new
      @user = User.new
      #@user.organisation_unit = OrganisationUnit.new
      @organisation_units = OrganisationUnit.find(:all, :order => "unit_code").map {|u|   [u.unit_code + " - " + u.unit_name, u.id]}
      respond_to do |format|
        format.html # new.html.erb
        format.xml  { render :xml => @user }
      end
    end

    # POST /users
    # POST /users.xml
    def create
      @user = User.new(params[:user])
      @user.organisation_unit = OrganisationUnit.find(params[:organisation_unit])
      @profile_picture = ProfilePicture.new(:uploaded_data => params[:profile_picture_file])
      @service = UserService.new(@user, @profile_picture, @department)
      respond_to do |format|
        #if @user.save
        if @service.save
          flash[:notice] = "User '#{@user.first_name} #{@user.last_name}' was successfully   created."
          format.html { render(:action=> 'index')}
          format.xml  { render :xml => @user, 
                               :status => :created,
                               :location => @user }
        else
          format.html { render :action => "new" }
          format.xml  { render :xml => @user.errors,
                               :status => :unprocessable_entity }
        end
      end
    end

  <end>

Finally, this is the code in my new.html.erb file in the Users view:

<% error_handling_form_for(@user, :html => {:multipart => true}) do |f| %>
  <%= f.error_messages %>

  <fieldset>
    <legend>Enter User Details</legend>

    <%= f.text_field :first_name, :size => 40, :class => 'mandatory' %>
    <%= f.text_field :last_name, :size => 40, :class => 'mandatory' %>
    <%= f.text_field :username, :size => 40, :class => 'mandatory' %>
    <%= f.password_field :password, :size => 40, :class => 'mandatory' %>
    <%= f.password_field :password_confirmation, :size => 40, :class => 'mandatory' %>

    <div>
      <span class='field_label'><%= label :user, "Profile Picture:"  %></span>
      <%= file_field_tag :profile_picture_file, :size => 40 %>
      <div id="hint">
        Please select a JPEG, PNG or GIF file of up to 500 Kilobytes
      </div>
    </div>

    <% fields_for @user.organisation_unit do |org| %>
      <%= org.select(:organisation_unit, @organisation_units) %>
    <% end %>

    <div class="center">
      <%= f.submit "Add User", :class => "submit" %>
    </div>

  </fieldset>

<% end %>

I've used Recipes 18 (Upload images with thumbnails) and 30 (Keep forms DRY and flexible) from 'Advanced Rails Recipes)

Last edited by rymeld (2009-10-29 01:20:03)

Re: Multiple Models in One Form: How to create the parent?

Look in your Create action for your UserController.  You may not be getting a valid org unit id.

@user.organisation_unit = OrganisationUnit.Find(params[:organisation_unit])

Try adding:
logger.info "ORG ID: " + params[:organisation_unit].inspect
and check the log/development log
to see what unit you are actually getting.  Is it still 20 as above?

Also, is there an organisation_unit with an ID of 20?

Drop to the console  (./script/console) and try:

OrganisationUnit.find(20)  # or whatever the ID was.  Still get the error?

Re: Multiple Models in One Form: How to create the parent?

Thanks for posting, cbmeeks.

The organisation units all exist 'cos I'm passing the view an array of them using this line in the new method of my UsersController:

@organisation_units = OrganisationUnit.find(:all, :order => "unit_code").map {|u| [u.unit_code + " - " + u.unit_name, u.id]}

I'm struggling with the right way of associating a parent object (a department) with a child object (a user).

I thought that using fields_for on the parent would allow me to get the organisation_unit object from the model and then associate that with the child using the belongs_to and has_many declarations but it's not working!!!

I've been hammering away at it for 4 days now and I'm starting to depair!!!