0

I am studying the source code for fat free CRM. I am trying to understand what this specific line of code in one of the app helpers does:

options[:selected] = (@account && @account.id) || 0

It seems to be setting the value of the options hash with key :selected to the value of the instance variable @account or 0 (if @account doesn't exist).

What is the && @account.id doing?

James Chevalier
  • 10,604
  • 5
  • 48
  • 74
Evan V
  • 1,837
  • 1
  • 12
  • 10

4 Answers4

7

It's making sure @account isn't falsey, and if it isn't, it sets the option to the account's id. Written long-hand it would be equivalent to this:

options[:selected] = if @account && @account.id
                       @account.id
                     else
                       0
                     end

Or

options[:selected] = (@account && @account.id) ? @account.id : 0

I'd probably use the andand gem which makes it look like this:

options[:selected] = @account.andand.id || 0
Dave Newton
  • 158,873
  • 26
  • 254
  • 302
0

It is equivalent to writing,

options[:selected] = (@account != nil ? (@account.id != nil ? @account.id : 0) : 0)

however, Ruby programmers prefer the way you have indicated in your question as you can see that above code can get really unreadable. Also, Ruby (and other dynamic programming languages such as JavaScript) have concept of truthy and falsy values which allows one to write concise and more readable code. You can read about that here in this article: A question of truth.

Wand Maker
  • 18,476
  • 8
  • 53
  • 87
0

Since it is a very common problem to ensure that an object is not nil, there is a method for that in rails (but not in ruby directly):

options[:selected] = @account.try(:id) || 0

try(:id) will return nil if @account is nil or false and will call :id on @account in any other case. That means also that it will raise an error, if the object is not nil or false and does not respond to id.

Lars Schirrmeister
  • 2,215
  • 1
  • 22
  • 23
0
options[:selected] = (@account && @account.id) || 0

This line of code will not set options[:selected] to be @account or 0, but rather @account.id or 0. The reason being that (@account && @account.id) will return the last statement evaluated, which would be @account.id if both are true.

As others have said, (@account && @account.id) is going to first verify that @account actually exists; if it does, thanks to short-circuiting, it will then check if @account.id exists and will set options[:selected] to it if it does. If, however, @account does not exist, then the value will be set to 0.

Daniel Brady
  • 934
  • 3
  • 11
  • 27