In Ruby, the && operator joins two true clauses, equivalent to asking "are A and B both true?" One of the more common uses for && is checking to see if an object exists before asking it for an attribute.
if a && a.b "hi" end
If we didn't check for 'a' before checking a.b, we could be asking the wrong guy about b... as in "'Hey, Mr. Nothin' - you know anything about this 'b' thing?"
Let's just say Nil (Mr. Nothing) usually throws a fit when you ask him that sort of question. But if we check for 'a' AND 'a.b' and 'a' doesn't exist, Ruby doesn't evaluate the second half of the expression. Nil gets left alone. (to be fair, most Ruby objects shout pretty loud when you ask them about a method they don't have. Some get creative and come up with things on the fly, though!)
In Rails applications, you'll commonly see:
if (user = User.find(params[:id])) && phone = user.phone_number puts phone end
Which boils down to "if 'user' exists, then get me attribute 'phone_number' of 'user' as 'phone'"
And that's the pattern 'andand' was created to simplify. To keep Nil and friends quiet and make the pattern more elegant.
if phone = user.andand.phone_number puts phone end
#et is an alias for #andand for brevity. "Et" is Latin for 'and'. This works the same as 'andand', but is much shorter! ;)
if phone = user.et.phone_number puts phone end
#ask is another alias for #andand. I like it the most because it describes what the pattern actually does: we ask "user, are you there, and what's your phone number?" Since we're asking nicely and not demanding an answer, our objects won't throw a fit.
if phone = user.ask.phone_number puts phone end
Yet another alias, this one providing the positive equivalent of 'aint', syntactically useful for places where you'd use 'andand' when checking that a boolean attribute is true.
user.destroy if user.is.revoked?
works the same as
user.destroy if user && user.revoked?
if user && !user.cancelled?
Here we're checking if our user exists before checking to make sure that they haven't cancelled their account. Effectively, we want user to exist and cancelled to be false, which is why we have that (!) before the second 'user'.
Using #andand in this case won't work, because the 2nd half will evaluate to false, and stop our friendly 'if' block.
So what do we do? How would we say it in English? "if it ain't broke, don't fix it", right?
Why not do that in Ruby?
puts "Don't fix it!" if it.aint.broken?
works the same as
if it && !it.broken? puts "Don't fix it" end
For those who aint from the northeast and say 'ant' when they mean their 'aunt', Object#aint is also aliased as:
#is_not #isnt #andnot
NOTE: be wary of using 'unless' with Object#is or Object#aint -- if the method doesn't exist on the receiver (it does not respond to revoked?), both #is and #aint return nil, which can be wicked bad if you don't grok your logic.
ONE MORE NOTE: #is and #aint are intended for safely checking boolean methods. Other uses are expressly not covered under any warranty ;)
andand >= 1.3.1
sudo gem install wideopenspaces-wicked
If using in Rails 2.2+, add the following line to config/environment.rb:
config.gem "wideopenspaces-wicked", :lib => 'wicked'
MIT
Jacob Stetser (jake@wideopenspac.es)
Jacob Stetser (jake@wideopenspac.es)
You can download this project in either zip or tar formats.
You can also clone the project with Git by running:
$ git clone git://github.com/wideopenspaces/wicked