Avoiding nil object error?


#1

I’m a total Rails newbie and i’ve been struggling for hours today
with one (prolly very silly) problem:

I have a table portfolios that has many images:

class Portfolio < ActiveRecord::Base
has_many :images
end

class Image < ActiveRecord::Base
belongs_to :portfolios
end

In the controller i define a list of active portfolios:

@active_portfolios = Portfolio.find_all_by_is_active(“1”)

In the view i render the list of portfolios:
<%= render :partial => “portfolio_list”, :collection =>
@active_portfolios %>

in the partial collection _portfolio_list i need to get the
image_url of the first image of the portfolio:

This works fine if every portfolio has at least one image assigned to
it. However, if a portfolio doesn’t have any images yet, the whole
thing falls apart and the app exits with the error:

“You have a nil object when you didn’t expect it!”

I tried to get around it by doing this in the portfolio model:

def get_first_image
self.images[0].image_url || “default.jpg”
end

and then in the partial:

but the exact same thing happens. If every portfolio has at least one
image it works well, if not, the error comes up. How can i avoid
errors on nil objects and instead define alternatives (e.g.
default.jpg) if a child attribute does not exist ?

Thanks for your help.
Sebastian


#2

@active_portfolios = Portfolio.find_all_by_is_active(“1”)

In the view i render the list of portfolios:
<%= render :partial => “portfolio_list”, :collection => @active_portfolios
%>

<% unless portfolio.images[0].nil? -%>

<% end -%>

#3

That’s the ticket. :slight_smile: Thank you so much.
sebastian


#4

you were very close with your get_first_image method

class Portfolio << ActiveRecord::Base

define a default image url

DEFAULT_IMG = “default.jpg”

return the first image url in the portfolio or a default image if no

images exist
def first_image
(images.empty?) ? DEFAULT_IMG : images[0].image_url
end
end

then in your view:

this has the benefit of removing the logic from the view and into the
portfolio where it belongs.


#5

end

then in your view:

this has the benefit of removing the logic from the view and into the
portfolio where it belongs.

good suggestion! for those of us without a C/C++ background:

def first_image
if images.empty? then DEFAULT_IMG else image[0].image_url end
end


#6

I had ended up doing this in similar (but much uglier) way all in the
view:

<img src="<%= portfolio_list.images[0].nil? ? “default.jpg” :
portfolio_list.images[0]. image_url -%>" />

but i certainly like your suggestion much better, especially when it
comes to quickly changing the defaults etc. I’m still trying to get
into the mindset of MVC separation and these kind of suggestions help
very much. Thanks.

Sebastian