Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I avoid nil checking in Rails views?

In my models, there are lots of attributes and methods that perform some calculation based on the model instance's attributes. I've been having the methods return nil if the attributes that the calculations depend on are nil. As a consequence of this design decision, I'm doing a lot of nil checks before displaying these values in my views.

I thought about having these methods return zero instead of nil when they don't have enough information, but I chose nil because zero is a valid computation result and nil implies that there was not enough information.

Should I return 0 instead of nil? Is there any other pattern that I could use to avoid doing a bunch of nil checks in my views?

like image 758
HB. Avatar asked Nov 12 '08 07:11

HB.


People also ask

How do you handle nil in Ruby?

However, in terms of how it's implemented, nil is fundamentally different than in other languages. In Ruby, nil is—you've guessed it—an object. It's the single instance of the NilClass class. Since nil in Ruby is just an object like virtually anything else, this means that handling it is not a special case.

Does Ruby return nil by default?

By default methods in Ruby are empty, and an empty method returns, by default, nil.

What is nil in rails?

Well, nil is a special Ruby object used to represent an “empty” or “default” value. It's also a “falsy” value, meaning that it behaves like false when used in a conditional statement. Now: There is ONLY one nil object, with an object_id of 4 (or 8 in 64-bit Ruby), this is part of why nil is special.

Is nil check Ruby?

In Ruby, you can check if an object is nil, just by calling the nil? on the object... even if the object is nil. That's quite logical if you think about it :) Side note : in Ruby, by convention, every method that ends with a question mark is designed to return a boolean (true or false).


4 Answers

I tend to think you are doing things right if your problem is choosing whether to display, or not display, the results of a calculation. If it would make no sense to display any value, then nil is perfectly reasonable.

If, however, your business logic is resulting in you getting into a state where much of the view will be habitually blank, then you probably should refactor such that your program loses its leaky abstractions.

Consider, for example, an application which starts by tracking recipes for Food. Then, as requirements morph, we get the notion of pies needing to display different information than burgers. Rather than having a calculate_deliciousness_of_pie_or_nil_for_burger method, and then checking for nil in the view, I'd break that into a pie view for pies and a burger view for burgers. This might (probably would) require rethinking my object abstractions.

like image 103
Patrick McKenzie Avatar answered Oct 30 '22 00:10

Patrick McKenzie


"I'm doing a lot of nil checks before displaying these values in my views."

I think returning nil is a good idea. An alternative that I sometimes use is to return a hash. For example, if a method succeeded, I might return:

{:result => 1234}

and if the method "failed", I might return:

{:error => 'Insufficient attributes to calculate result.'}

This makes it trivial to determine the outcome without guessing.

With that said, make sure that you create helper methods to call these methods and check their results. Views should contain very little logic. So rather than doing this to control whether or not the result is displayed:

<% if result = some_method -%>
  Your result is <%=h result -%>.<br />
<% end -%>

You should do this:

<% display_some_method %>

and #display_ some_ method is located in app/helpers/whatever_helper.rb .

like image 24
nickh Avatar answered Oct 30 '22 01:10

nickh


This SO question might provide you some insight on the nil or zero pattern:

Best Ruby idiom for “nil or zero”

like image 2
mwilliams Avatar answered Oct 30 '22 01:10

mwilliams


I attack this problem using two approaches.

I try to move more demanding checks into the model. For instance, method Apartment#address_visible?(current_user) makes it much more cleaner.

Since Rails 2.3 there is also #try method that calls a method only if it is already defined. It can be easily included into your project using chris' example. This is for the most simple cases.

like image 1
maurycy Avatar answered Oct 30 '22 02:10

maurycy