Newbie Problem

I’m new to Ruby, so I’m sure this is an easy one.

I have the following class:


class Pilot < ActiveRecord::Base
  validates_presence_of :last_name, :first_name, :middle_name, :birth_date
  has_many :flights, :dependent => :destroy 
  has_many :aircraft
  
  def flight_count
    return flights.length
  end

  def full_name
    puts "full_name()"
    name = ""
	if @first_name != nil then 
	  name += @first_name 
	end
    puts "@first_name = \\"#{@first_name}\\" name = \\"#{name}\\""
	if @middle_name != nil then 
		name += " " + @middle_name 
	end
    puts "@middle_name = \\"#{@middle_name}\\" name = \\"#{name}\\""
	if @last_name != nil then 
		name += " " + @last_name 
	end
    puts "@last_name = \\"#{@last_name}\\" name = \\"#{name}\\""
    puts "full_name() returns \\"#{name}\\""
	return name
  end
  
  def inspect
	return to_s
  end

  def to_s
	return "Pilot [#{id}](name = \\"#{self.full_name}\\" birth_date = " + (birth_date == nil ? "nil" : birth_date.to_formatted_s(:short)) + " flights = " + flight_count.to_s + ")"
  end
end

When I call the full_name method from a web page, it returns the full name as expected. But when I call if from the to_s method, it returns an empty string because first_name, last_name, and middle_name are empty strings. Here’s the console output:


C:\\Ruby\\projects\\logbook>ruby script/server
=> Booting Mongrel
=> Rails 2.3.5 application starting on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
new() pilot_id: "2"
full_name()
@first_name = "" name = ""
@middle_name = "" name = ""
@last_name = "" name = ""
full_name() returns ""
pilot = "Pilot [2](name = "" birth_date = 12 Oct flights = 1)"
full_name()
@first_name = "" name = ""
@middle_name = "" name = ""
@last_name = "" name = ""
full_name() returns ""
pilot = "Pilot [2](name = "" birth_date = 12 Oct flights = 1)"
full_name()
@first_name = "" name = ""
@middle_name = "" name = ""
@last_name = "" name = ""
full_name() returns ""


Processing FlightsController#new (for 127.0.0.1 at 2010-04-13 21:46:55) [GET]
  Parameters: {"pilot_id"=>"2"}
  &#8592;[4;36;1mPilot Load (0.0ms)&#8592;[0m   &#8592;[0;1mSELECT * FROM "pilots" WHERE ("pilots"
."id" = 2) &#8592;[0m
  &#8592;[4;35;1mFlight Load (0.0ms)&#8592;[0m   &#8592;[0mSELECT * FROM "flights" WHERE ("flights
".pilot_id = 2) &#8592;[0m
Rendering template within layouts/flights
Rendering flights/new
Rendered flights/_form (1047.0ms)
Completed in 2422ms (View: 1359, DB: 0) | 200 OK [http://localhost/pilots/2/flig
hts/new]

Any ideas what I’m doing wrong?

It looks to me that you are making things far more complicated that they need to be. You seem to be loading a pilot (2) at server start which is an unusual thing to do. I’d recommend that you start from scratch as you seem to be jumping in without really understanding what is going on. Try working through one of the many Rails books: for example the Sitepoint book or [URL=“http://pragprog.com/titles/rails2/agile-web-development-with-rails”]Agile web development with Rails

For example your Pilot model can be simplified to this:


class Pilot < ActiveRecord::Base
  validates_presence_of :last_name, :first_name, :middle_name, :birth_date
  has_many :flights, :dependent => :destroy 
  has_many :aircraft
  
  def flight_count
    return flights.length
  end

  def full_name
    [first_name, middle_name, last_name].compact.join(" ")
  end
  
end

An inspect method already exists for a model, and is useful for most things. If you want a specially formatted output, it would be better to use a custom method rather than overload ‘inspect’. Especially as inspect is used in unit test failure output, and therefore you could easily lose useful information if you overloaded the inspect.

Also to_s has a fairly simple function in classes where it is used. Making your own version of it that are rather complex, probably isn’t a good idea. Again, you’d be better using a custom method name that describes what the method does. For example, pilot_summary.