Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby default assignment ( ||= ) vs Rescuing error

Since a ||= 1 is equivalent to a || a = 1, one can state that this is synctactic sugar for this:

if a.nil?
  a = 1
end

Likewise, given that session is a hash-like object, the following:

def increment_session_counter
  session[:counter] ||= 0
  session[:counter] += 1
end

is equivalent to:

def increment_session_counter
  if session[:counter].nil?
    session[:counter] = 0
  end
  session[:counter] += 1
end

Does that mean that the implicit if statement will be executed every time in the original definition of increment_session_counter? Since session[:counter] will mostly likely be nil only the first time (i.e. << 1% of the time), I have the feeling that the following code is better, since the implicit if won't be fired every time:

def increment_session_counter
  session[:counter] += 1
rescue NoMethodError
  session[:counter] = 1
end

Is this code better in such sense?

Having said that, I have no idea how Rescue is implemented in ruby and whether it's actually relevant regarding the tiny little optimization that can bring if so.

like image 917
SanjiBukai Avatar asked Jun 12 '17 05:06

SanjiBukai


1 Answers

session[:counter] += 1 does three things:

  1. fetch the value (Hash#[])
  2. increment the value (Integer#+)
  3. store the incremented value (Hash#[]=)

That's pretty convenient, but its brevity also makes it inflexible.

Providing a default is much easier if you separate the steps:

def increment_session_counter
  session[:counter] = session.fetch(:counter, 0) + 1
end
like image 197
Stefan Avatar answered Sep 22 '22 20:09

Stefan