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?
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.
By default methods in Ruby are empty, and an empty method returns, by default, nil.
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.
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).
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.
"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 .
This SO question might provide you some insight on the nil or zero pattern:
Best Ruby idiom for “nil or zero”
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With