Forum: Ruby on Rails avoiding nil object error?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
10c741d575988433e3fcd04133f3c462?d=identicon&s=25 Sebastian Friedrich (Guest)
on 2006-03-03 07:35
(Received via mailing list)
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:
<td class="col1"><img src="<%= portfolio_list.images[0].image_url -%
 >" /></td>

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:
<td class="col1"><img src="<%= portfolio_list.get_first_image -%>" /
 ></td>

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
720fde074c77f4c9692dd6f05802d581?d=identicon&s=25 Nithin Reddy (jashugan)
on 2006-03-03 07:44
(Received via mailing list)
>
> @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? -%>
  <td class="col1"><img src="<%= portfolio_list.images[0].image_url -%>"
/></td>
<% end -%>
10c741d575988433e3fcd04133f3c462?d=identicon&s=25 Sebastian Friedrich (Guest)
on 2006-03-03 07:56
(Received via mailing list)
That's the ticket. :) Thank you so much.
sebastian
A2c85dc5ee81b12e3cc0a6522e8d079d?d=identicon&s=25 Chris Hall (Guest)
on 2006-03-03 16:09
(Received via mailing list)
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:

<img src="<%= portfolio.first_image -%>"/>

this has the benefit of removing the logic from the view and into the
portfolio where it belongs.
10c741d575988433e3fcd04133f3c462?d=identicon&s=25 Sebastian Friedrich (Guest)
on 2006-03-03 18:37
(Received via mailing list)
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
720fde074c77f4c9692dd6f05802d581?d=identicon&s=25 Nithin Reddy (jashugan)
on 2006-03-03 19:35
(Received via mailing list)
> end
>
> then in your view:
>
> <img src="<%= portfolio.first_image -%>"/>
>
> 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
This topic is locked and can not be replied to.