This project is archived and is in readonly mode.
Add or_if_blank to Object
Reported by Ryan Angilly | January 29th, 2009 @ 05:29 AM | in 2.x
A utility method so that instead of having to write:
self.association_proxy.email.blank? ? self.name : self.association_proxy.email
all over the place, you can just write:
self.association_proxy.email.or_if_blank self.name
Works wherever blank? is defined.
Discussed on this thread: http://groups.google.com/group/r...
Comments and changes to this ticket
-
Aliaksey Kandratsenka January 29th, 2009 @ 06:43 AM
I'm not sure if its good idea, because there's a significant difference with '||'. Usual 'or' is short-circuiting, while this method cannot work that way.
I think that this should at least be noted in the documentation of this method, so that people don't try things like '.or_if_blank? raise', or '.or_if_blank? <do_something_else_expensive>'
And BTW some time ago my co-worked showed me some blog post where some dude proposed '|' for same operation. You might want to consider this syntax, although I think that will be worse, because of the above mentioned non-short-circuiting behavior.
-
Matt Jones January 29th, 2009 @ 07:01 AM
The only way I could see to get short-circuit behavior would be to pass a block; it would look kind of weird:
object.param.or_if_blank { object.other_param }
Just a thought.
-
Matt Jones January 29th, 2009 @ 07:07 AM
Had a thought just after posting - it wouldn't be as generic as the above, but what about an operator like or ?
So the above would be:
object.param._or_.other_param
There'd be some interesting trickery needed (see the implementation of SafeNil for ideas), but it would be pretty clear. Of course, I'm a little biased as I've gotten spoiled by hobosupport's _? operator (equivalent to try).
-
Josh Susser January 29th, 2009 @ 07:40 AM
I was going to suggest the block as an option. It's easy to do:
def or_if_blank(other=nil) self.blank? ? (other || yield) : self end
Then you can call it with either an immediate value or a block to get the value with a deferred computation.
person.nickname.or_if_blank(person.full_name)
person.nickname.or_if_blank { person.full_name }
-
tf January 29th, 2009 @ 12:16 PM
I really like the idea of adding lazy evaluation by passing a block. A little note in the docs can point out the difference between "? :" and or_if_blank.
-
MatthewRudy January 29th, 2009 @ 12:16 PM
Interesting.
But I like my BumbleBee approach, which is inline with how :try is implemented
person.try(:nickname) || person.full_name # if you care about a :nil? nickname person.bumblebee(:nickname, :full_name) # if you care about a :blank? nickname
or with fuller defaulting
person.bumblebee(:nickname, :full_name) || "unknown"
My full gist on the matter is here; http://gist.github.com/54501
-
MatthewRudy January 29th, 2009 @ 12:17 PM
(notably the bumblebee doesn't know anything about args or blocks, which :try does)
-
tf January 29th, 2009 @ 12:33 PM
The bumblebee is kind of cool. Still it does not cover slightly more complex cases:
person.hometown.or_if_blank { person.address.town }
Silly example. You get the idea.
-
Pratik January 29th, 2009 @ 06:16 PM
- State changed from new to wontfix
- Title changed from [PATCH] Add or_if_blank to Object to Add or_if_blank to Object
I don't really think we need to add any of these methods. try() is for a common pattern inside the views. or_if_blank seems like code smell.
-
Ryan Angilly January 30th, 2009 @ 02:31 AM
try() doesn't help with blank strings, which was the whole point of what I was suggesting.
And out of curiosity, what's the relevance of try()'s usage in views? I use my own version of or_if_blank in models, controllers, and helpers just as much as in views.
-
tf January 30th, 2009 @ 11:41 AM
If this functionality is not wanted - for whatever reason - I'd consider packaging it up as a gem. Still I have to agree that I do not see how try could be of any help in this use case.
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
<h2 style="font-size: 14px">Tickets have moved to Github</h2>
The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>