Best way of handling nils in views?

I find myself writing ugly code like the following a LOT:

<%=emp.title%> <%=emp.department.name if !emp.department.nil? %> <%=emp.site.name if !emp.site.nil?%> <%=if (!emp.site.nil? and (!emp.site.phone.nil? or ! emp.site.phone.empty?)) emp.site.phone else " " end%>

Notice all those nil? checks? Is there no easier or cleaner way of
doing this?

Thanks,
Jake

Or…if you use table borders, you end up doing an even uglier
solution to avoid non-rendered cells for empty contents in Gecko-based
browsers (like Firefox):

<%=emp.last_name || " "%> <%=emp.first_name || " "%> <%=emp.title || " " %> <%=if !emp.department.nil?: emp.department.name else "&nbsp"; end %> <%=emp.site.name if !emp.site.nil?%> <%=if (!emp.site.nil? and (!emp.site.phone.nil? and !emp.site.phone.empty?)) emp.site.phone else " " end%> <%=emp.extension || " " %> <%=emp.mobile || " "%> <%=emp.pager|| " "%> <%=emp.alternate_phone|| " "%>
   end%>

Notice all those nil? checks? Is there no easier or cleaner way of
doing this?

Well, you could disable the whiny nil in config/environments/… or you
could fix them in the controller/model before they get to your view, or
you could do one of these which is a little nicer:

obj.attr unless obj.attr.nil?
obj.attr rescue ’ ’

You might also try .blank? instead of .nil? in your   cases.

-philip

On 2/10/07, Jake C. [email protected] wrote:

      "&nbsp;"
    end%>

Notice all those nil? checks? Is there no easier or cleaner way of
doing this?

Hmm, perhaps one of those “message-eating nils” [1] might have a place
here:

class Object
def blanker
Blanker.new(self)
end
end

class Blanker
instance_methods.each{|name| undef_method(name) unless name =~
/\A__/}
def initialize(receiver)
@receiver = receiver
end
def to_s
@receiver.to_s
end
def method_missing(*args)
unless @receiver.nil?
@receiver = @receiver.send(*args)
end
self
end
end

Now, <%= emp.blanker.department.name %> should do what you want.

A few other points:

<%=if (!emp.site.nil? and (!emp.site.phone.nil? or ! emp.site.phone.empty?)) emp.site.phone else " " end%>

activesupport lets you replace (foo.nil? || foo.empty?) with
foo.blank? (I’m assuming you typo’d the logic a bit there…)

That gets us to:

<%=if !emp.site.nil? && !emp.site.phone.blank? emp.site.phone else " " end%>

As for the ’ ’ thing, you might like to define an #or_nbsp method:

class Object
def or_nbsp
str = to_s
str =~ /\S/ ? str : ’ ’
end
end

Which gets us to:

<%=(emp.site && emp.site.phone).or_nbsp %>

Or, combining with the #blanker thing above:

<%=emp.blanker.site.phone.or_nbsp %>

Thanks,
Jake

Welcome!
George.

[1] http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/17785

On 2/12/07, Charly [email protected] wrote:

AS a general “good practice” (skinny controller & views, fat model)
this is more for the Business logic job:
theres a very conveniant function called delegate. Here’s more info
about it :
http://brian.maybeyoureinsane.net/blog/2006/12/15/law-of-demeter-or-how-to-avoid-coding-yourself-into-a-corner-in-rails/

Hi Charly,

Thanks for the link.

Yeah, that’s a good point about Demeter; I guess that’s another
oft-cited reason to discourage the message-eating-nil thing.
Unfortunately though, #delegate won’t check for nils. Not that you
couldn’t define your own variant which does easily enough.

George.

AS a general “good practice” (skinny controller & views, fat model)
this is more for the Business logic job:
theres a very conveniant function called delegate. Here’s more info
about it :
http://brian.maybeyoureinsane.net/blog/2006/12/15/law-of-demeter-or-how-to-avoid-coding-yourself-into-a-corner-in-rails/

On 2/12/07, George O. [email protected] wrote:

Hi Charly,

Thanks for the link.

Yeah, that’s a good point about Demeter; I guess that’s another
oft-cited reason to discourage the message-eating-nil thing.
Unfortunately though, #delegate won’t check for nils. Not that you
couldn’t define your own variant which does easily enough.

George.

This doesn’t sound right in my own ears but I can’t put my finger on
why.
What if the method_missing in Nil was replaced by something like

class Nil

def method_missing( method, *args, &block )
nil
end

end

This way if there is a nil at any point along the chain at the end it
will
be a nil. Eg, if department is nil, name will also return nil

<%= emp.department.name || “No Department Set” %>

Just a thought, but is there anything wrong with this approach?

You could take a look at the Null Object pattern, if appropriate for
your model. I’ve find this quite handy in my RoR apps. A link with an
implementation for active record associations below:

http://blog.craigambrose.com/articles/2006/09/22/active-record-associations-and-the-null-object-pattern

Cheers,
Roland

On 2/13/07, Daniel N [email protected] wrote:

Hi Charly,

This way if there is a nil at any point along the chain at the end it will
be a nil. Eg, if department is nil, name will also return nil

<%= emp.department.name || “No Department Set” %>

Just a thought, but is there anything wrong with this approach?

It’s been discussed at length before:

http://rubyurl.com/S8A

I think the main argument is it can hide errors easily (or make them
harder to track down). For example, if you typo’d a method name, it’d
treat it the same as if the attribute was nil.

Regards,
George.

On 2/14/07, George O. [email protected] wrote:

http://brian.maybeyoureinsane.net/blog/2006/12/15/law-of-demeter-or-how-to-avoid-coding-yourself-into-a-corner-in-rails/

George.

http://rubyurl.com/S8A

I think the main argument is it can hide errors easily (or make them
harder to track down). For example, if you typo’d a method name, it’d
treat it the same as if the attribute was nil.

Regards,
George.

Thanx for the link. That was a great thread on the subject.

On 2/11/07, George O. [email protected] wrote:

class Object
def or_nbsp
str = to_s
str =~ /\S/ ? str : ’ ’
end
end

This works nicely. Thanks George!

On 2/13/07, Roland S. [email protected] wrote:

Roland
Roland,

Thanx for the link, I noticed in the comments that Craig has shown nil
chaining as well but distances himself from it. This confirms my
suspicion
that there may be something wrong with doing this but for the life of me
I
don’t know what.

Cheers
Daniel