Topic: Models with relatonships (in this case Parent-Child)

I've been standing on the shoulders of giants, and now I've fallen off!

I've been using Recipe 30 in 'Advanced Rails Recipes' to keep my forms DRY. I'm trying to create a form to allow users to register. I want to create a new User but I also want to associate that user with an existing Organisation Unit (e.g. a department).

I've created associations in my models:

class User < ActiveRecord::Base

  . . . 

  belongs_to :organisation_unit

  . . .

<end>

class OrganisationUnit < ActiveRecord::Base

   . . .
  
  has_many :users

  . . . 

<end>

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

    <% fields_for(@user.organisation_unit, :builder => ErrorHandlingFormBuilder) do |org| %>
      <%= f.select(:organisation_unit, @organisation_units) %>
    <% end %>
    
    <div class="center">
      <%= f.submit "Add User", :class => "submit" %>
    </div>

  </fieldset>

<% end %>

I'm getting a NoErrorMethod:

undefined method `Find' for #<Class:0x46ac3b4>

RAILS_ROOT: C:/Documents and Settings/David/My Documents/Sapien/Web Software/sapience
Application Trace | Framework Trace | Full Trace

Parameters:

{"user"=>{"password_confirmation"=>"primera",
 "username"=>"smithg",
 "first_name"=>"Geoff",
 "last_name"=>"Smith",
 "password"=>"primera"},
 "commit"=>"Add User",
 "authenticity_token"=>"ih5/WnVH7fdiIHOnVbV0aWu7IPBwA0vjZ80YF4pq1qc=",
 "nil_class"=>{"organisation_unit"=>"10"}}

I hope someone can help me with this?

Many thanks,

David

Re: Models with relatonships (in this case Parent-Child)

Normally the error would list a specific file and a line number, i'm not sure why it doesn't.  Does your main folder name have a space in it?  If so then change the folder name.  I'd strongly recommend making sure that your development path doesn't have any spaces at all, just for safety's sake, which means DO NOT put it in 'My Documents' or "Web Software".  Generally when coding *anything* it's best to make all of the folder names lower case and with underscores instead of spaces.

Anyway, if there was a line number it would point you to this line:

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

undefined method `Find' for #<Class:0x46ac3b4>

it should be .find, not .Find.  That's what the error is telling you, there's no .Find method.  Method names should always be lowercase.

###########################################
#If i've helped you then please recommend me at Working With Rails:
#http://www.workingwithrails.com/person/ … i-williams

Re: Models with relatonships (in this case Parent-Child)

I feel like such a fool!!

Thanks, Max.  I'd copied a selected portion of the error page that got served up: that's why it was incomplete. And I've taken your (good) advice to change the location of my project.

I changed 'Find' to 'find' and now I'm getting this:

Couldn't find OrganisationUnit without an ID

RAILS_ROOT: C:/sapien/web_software/sapience
Application Trace | Framework Trace | Full Trace

C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/base.rb:1572:in `find_from_ids'
C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/base.rb:616:in `find'
C:/sapien/web_software/sapience/app/controllers/users_controller.rb:44:in `create'

Request

Parameters:

{"user"=>{"password_confirmation"=>"primera",
 "username"=>"bloggj",
 "first_name"=>"Joe",
 "last_name"=>"Bloggs",
 "password"=>"primera"},
 "commit"=>"Add User",
 "authenticity_token"=>"ih5/WnVH7fdiIHOnVbV0aWu7IPBwA0vjZ80YF4pq1qc=",
 "nil_class"=>{"organisation_unit"=>"25"}}

The last line is wrong, but although I understand how to specify active_record relationships, I don't know how to code the form. I'm using fields_for with @user.organisation_unit and there are a bunch of organisation_units already created. A User would never create a new Organisation_Unit: they'd select a pre-existing one that they are a member of. Why does @user.organisation_unit show up in the html as "nil_class =>{"organisation_unit" => "25"}}"?

Thanks,

David