Really, and I mean really easy question

Hello everybody,

Quick question. Let’s say I have model Person and has a belong_to
relationship to model Award through award_id. As you can imagine a
person may have no award. If I just say in the template:

<%= @person.award.name %> I will get the annoying ‘nil’ error when the
template is rendered if the person does not have an award – and I
have a lot of similar situations in my template. I could write:

<%= @person.award.name if @person.award %>, I guess, but is this the
best way to do it?

Thanks!

On Aug 4, 2008, at 11:24 AM, surge wrote:

<%= @person.award.name if @person.award %>, I guess, but is this the
best way to do it?

That’s what I do, unless it’s one particular thing that comes up
often. If so, then in the Person model I’d make an award_name method
that handled the nil case. Then the view would be

<%= @person.award_name %>

A more ambitious programmer might write a more generic equivalent,
which perhaps you’d call as

<%= @person.award_field(:name) %>

I would create a helper to display what information you want, pass in
the person and then return the award name or nothing. So for example
in your helper you would have:

def show_award_name(person)
unless person.award.name.blank?
person.award.name
else
“NA”
end
end

then in your view i would do:

<%= show_award_name(@person) %>

This would clean up your view and allow you to use if statements. Of
course you would need to modify this for a many awards situation.

-Chris


Solutions Developer / Consultant
Inacom Information Systems
http://www.inacom.com
(p) 608.661.7731

surge wrote:

Hello everybody,

Quick question. Let’s say I have model Person and has a belong_to
relationship to model Award through award_id. As you can imagine a
person may have no award. If I just say in the template:

<%= @person.award.name %> I will get the annoying ‘nil’ error when the
template is rendered if the person does not have an award – and I
have a lot of similar situations in my template. I could write:

<%= @person.award.name if @person.award %>, I guess, but is this the
best way to do it?

Thanks!

You could say

<%= @person.award.name.nil? ? ‘’ : @person.award.name %>

That way if it was nil nothing would be displayed (which may or may not
be what you want) but no error message will be thrown. I like this way a
lot better then using ‘if’.

Thanks for your replies, everybody. Because I have too many of these
fields, I’m not too crazy about writing helper methods. I got this
suggestion from somebody:

<%= @person.award.name rescue nil %> and I like the shortness of it.

But I really do appreciate your suggestions!

On Aug 4, 2008, at 1:32 PM, surge wrote:

Thanks for your replies, everybody. Because I have too many of these
fields, I’m not too crazy about writing helper methods. I got this
suggestion from somebody:

<%= @person.award.name rescue nil %> and I like the shortness of it.

If you have many fields from the award, you can wrap the whole thing
in an if block

<% if person.award %>

…several lines of award display code

<% else %>

some other display when there’s no award

<% end %>

2008/8/4 surge [email protected]:

<%= @person.award.name if @person.award %>, I guess, but is this the
best way to do it?

You could use raganwald’s andand gem. With it you could write:

<%= @person.award.andand.name %>

See http://andand.rubyforge.org/

Stefan

On 5 Aug 2008, at 18:21, Stefan B. wrote:

I’ve cloned the groovy nils behaviour into my rails app by simply
adding
groovy_nils.rb into congif/initializers

While this might deal with the simple case of removing some tedium
from a view, I really think you’re setting yourself up for a hard to
diagnose problem further down the line.
Either through not checking or through some exceptional condition you
end up with a nil instead of what you expected. Instead of failing
there and then your code continues silently until something really bad
happens.

Fred

Hey,

yeah I thought the exact same thing. You have to be carefull when doing
it that way. But for now, I love it. The risk of having some more work
debugging the code when I make a mistake is worth it.

Its not just about the views.
Long association chains? No problem…
if @user.address.street.abutters.first.company

end

Iterating over something? dont have to check for nil:
@user.sister.neighbors.each do |i|
sisterneighbors ||= []
sisterneighbors << i
end
sisterneighbors.dosomething

While unsure at first, I found that it simply “works”. Using it for
quite some time now and dont found a situation where it could break
alot.

On 5 Aug 2008, at 19:54, Stefan B. wrote:

While unsure at first, I found that it simply “works”. Using it for
quite some time now and dont found a situation where it could break
alot.

You could quite easily typo an instance variable name. Instead of
getting an error at that point what you were doing becomes a no-op
(obviously something like that would be caught by a unit test, but you
still have to spend the time to get from ‘nothing is happening’ to
‘that thing is nil’)

Fred

Yeah,

but there’s still the option not to do any typos :wink:

Stefan

I’ve cloned the groovy nils behaviour into my rails app by simply adding
groovy_nils.rb into congif/initializers

grooby_nils.rb

class NilClass
    def method_missing *dontcare
        return nil
    end
end

http://groovy.codehaus.org/Null+Object+Pattern

On Aug 4, 3:32 pm, surge [email protected] wrote:

Thanks for your replies, everybody. Because I have too many of these
fields, I’m not too crazy about writing helper methods. I got this
suggestion from somebody:

<%= @person.award.name rescue nil %> and I like the shortness of it.

Like the Groovy Nils solution, this trades brevity for correctness: if
you ever have another type of error–like a database problem where the
name column is missing or if you accidentally type nmae–you will
silently ignore the problem. This may be acceptable to you.

If you want a round-up of solutions, on my original blog post I tried
to summarize the approaches people have described to this common
issue. You may find them interesting:

http://weblog.raganwald.com/2008/01/objectandand-objectme-in-ruby.html

This pattern might work for you:

class Award
def to_s
name
end
end

<%= @person.award %>