Correct me if I’m mistaken. Please.
The people behind andand, try, do_or_do_not, NilClass#method_missing, SafeNil, maybe, etc. seem to be trying to beautifully solve the problem of calling methods on objects that might be nil and not having Ruby complain about it. They might be chaining methods a lot or, when they check if an object is nil, they use the ternary conditional and (rightly) think it’s ugly.
As for these ternary conditional users, you can do this: @person.name if @person instead of @person ? @person.name : nil. It does what you need, looks great, and is highly readable.
Of course, that doesn’t help you if you’re chaining methods.
But (and this is what’s been on my mind), I suspect that all of these solutions value terseness over readability and flexibility. It’s a trade off I’m willing to make sometimes, but I think it’s unnecessary here.
For example, Reg Braithwaite’s example:
@phone = Location.find(:first, ...elided... ).andand.phone
We’re trying to get the phone number of a location, but maybe we won’t find the location. Seems normal on the surface. But these are the questions that run through my mind looking at this:
- All you need is the phone number?
- You’re sure you don’t need anything else from the Location object? (address, url, hours, etc.)
- It doesn’t mean anything if the location isn’t found?
I find it hard to believe that the answer to all these questions is “Yes”. I know this is example code, but it must be inspired from something, right?
I’d bet that instead of @phone = Location.find(:first, ...elided... ).andand.phone, later on you’d really wish you had this:
@location = Location.find(:first, ...elided... )
Maybe you’d discover your view (Reg’s example is ActiveResource-related, I’m running with that) needs more than just the phone number (who are you calling?). Or maybe you’d discover that if the location isn’t found, that that means something. Maybe you need to alert the user (unless @location ...).
It could be that I’m more hung up on this idea of meaning. The example for Ben’s maybe is:
if(customer && customer.order && customer.order.id==newest_customer_id)
I look at that and think: if there’s no customer, that means one thing; if there’s no order for the customer, that means something else; if the customer’s order’s id isn’t newest_customer_id, that means something else entirely; and if all these things are different, maybe they should be handled separately.
If you think about it that way, there’s no need to fiddle with nil or add methods to Object.
(I completely understand that this might just be an aesthetic difference, or that sometimes this apparent loss of flexibility is desirable, or that I might be wrong. Please narrow it down for me in the comments. Thanks.)