Elusive Nil Object error on Comments

I have 2 models: Applicants and Comments. Applicants has_many
Comments and Comments belongs_to Applicant.

If I add validation to my Applicants model (for example,
“validates_presence_of :first_name”) and edit the applicants page, I
get a Nil Object error if I remove the first_name before saving. In
this case I would expect to see the “there was 1 error that
prevented…” error message. I do get this message during Applicant
creation.

The strange part is that the error I do get points to my comments
display. Everything works as expected. Why would it behave this way?

ERROR MESSAGE: Action Controller: Exception Caught

#################

Showing app/views/applicants/_comments.rhtml where line #42 raised:

You have a nil object when you didn’t expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.each

Extracted source (around line #42):

39:

Comment
40: File
41:
42: <% for comment in @comments %>
43:
44: <%= comment.created_at.to_s(:long) %>
45: <%=h comment.comment_type %>

CONTROLLER: applicants_controller.rb

def edit
@applicant = Applicant.find(params[:id])
@comments = @applicant.applicant_comments.find(:all)
end

def update
@applicant = Applicant.find(params[:id])
if @applicant.update_attributes(params[:applicant])
flash[:notice] = ‘Applicant was successfully updated.’
redirect_to :action => ‘list’
else
render :action => ‘edit’
end
end

def comment

Applicant.find(params[:id]).applicant_comments.create(params[:applicant_comment])
flash[:notice] = ‘comment was successfully created.’
redirect_to :action => ‘edit’, :id => params[:id]
end

MODEL: ApplicantComment.rb

class ApplicantComment < ActiveRecord::Base
belongs_to :applicant

has_attachment :storage => :file_system
end

MODEL: Applicant.rb

class Applicant < ActiveRecord::Base
has_one :contract
has_many :applicant_comments

validates_presence_of :first_name, :last_name, :email, :phone_1,
:address_1, :city, :state, :zip, :resume

def full_name
[last_name, first_name].join(’, ‘)
end
def full_name=(name)
split = name.split(’ ', 2)
self.first_name = split.last
self.last_name = split.first
end
end

VIEW: applicants/edit.rhtml

Edit applicant

<% form_tag :action => ‘update’, :id => @applicant do %>
<%= render :partial => ‘form’ %>

<%= image_submit_tag("save.png") %>
<% end %>

Post Comments

<% for comment in @comments %> <% end %>
Comment Created
<%= comment.body %> <%= comment.created_at %>

<% form_for(
:applicant_comment,
:url => {:controller => ‘applicants’ , :action => ‘comment’, :id =>
@applicant},
:html => { :multipart => true }
) do |form| %>

<%= form.hidden_field(“comment_type”, :value => “Hiring Process”) %>

Comment:
<%= form.text_area :body, :rows => 3, :cols => 40 %>

<%= link_to_function(("Attach File"), "Element.remove('file_link');Element.show('file')") %>
Upload a file:
<%= form.file_field :uploaded_data %>
<%= image_submit_tag("save.png") %>
<% end %>

<%= link_to ‘Back’, :action => ‘list’ %>

ebrad wrote:

  flash[:notice] = 'Applicant was successfully updated.'
  redirect_to :action => 'list'
else
  render :action => 'edit'
end

end

“render :action => ‘edit’” renders the edit template but does
not call the edit action which is seting the @comments variable.

Since you want to preserve the errors on @applicant, you’ll
have to copy down the @comments line.


We develop, watch us RoR, in numbers too big to ignore.

That’s exactly it! Thanks!

CONTROLLER: applicants_controller.rb

def edit
@applicant = Applicant.find(params[:id])
@comments = @applicant.applicant_comments.find(:all)
end

def update
@applicant = Applicant.find(params[:id])
if @applicant.update_attributes(params[:applicant])
flash[:notice] = ‘Applicant was successfully updated.’
redirect_to :action => ‘list’
else
@comments = @applicant.applicant_comments.find(:all)
render :action => ‘edit’
end
end