The Billy Baldwin of Conditional Assignment
In the world of Ruby’s conditional assignment operators,
||= is Alec Baldwin; charming and versatile. But not many people know about
||=’s little brother… the
||= conditional assignment operator is popular in Ruby and for good reason. One common usage is for simple memoization. Ryan Bates outlined this technique in his very first RailsCast.
def current_user @current_user ||= User.find(session[:user_id]) end
The purpose here is to avoid re-finding the user every time the
current_user method is called. The
||= operator above has the same effect as:
def current_user @current_user = @current_user || User.find(session[:user_id]) end
@current_user is both defined and truthy (not
nil), that value is simply returned. Otherwise the instance variable is set and returned.
Enough about Alec. What about Billy?
The magic of the
&&= operator is that it only sets variables that are… already set! The usefulness of this may not be immediately apparent, but maybe you’ve written code like this:
class Article < ActiveRecord::Base validates :title, :body, :presence => true before_save :clean_summary private def clean_summary self.summary = summary.squish end end
The problem with this code is that the article summary isn’t required. What if an article’s summary is
nil? We’ll get a
NoMethodError trying to call
squish 1 on
nil. Oftentimes, the fix looks like this:
def clean_summary self.summary = summary && summary.squish end
which looks eerily similar to our
current_user memoization expansion. So instead, try:
def clean_summary self.summary &&= summary.squish end
Sure, it’s a bit of a one-trick pony, but sometimes that one trick is exactly what you need. Have you ever seen Backdraft? Every dog has its day.
1 String#squish changes consecutive whitespace to single spaces.