Ruby Idiom: In-logic assignment

One of idioms we used to clean up in last weeks pair-refactor is a pretty common one that most ruby developers are familiar with but developers coming from elsewhere might not be.

Instead of:

if Book.exists?(:title => title) # SELECT #=> true/false
  book = Book.find_by_title(title) # SELECT #=> Book
  ...

Doing this:

if book = Book.find_by_title(title) # SELECT || nil
  ...

Because you can do assignments in-line with logic and because ActiveRecord#find_by_ doesn't raise an error and just returns nil if it fails, this works. Also, if the book does exist the second snippent only results in one query instead of two. Even though that might only take 5ms, multiply that by 1000 x 35,000 and that saves a lot of time.

Something I found out the hard way is that there is a bit of a gotcha with the order of operations. Doing side-by-side in logic assignments like:

if book = Book.find_by_title(title) && company = Company.find_by_name(name)
  ...  

Is actually equivalent to this:

if book = (Book.find_by_title(title) && company = Company.find_by_name(name))
  # book => (boolean)  
  # company => (<Company>) 

So pretty please place parentheses:

if (book = Book.find_by_title(title)) && (company = Company.find_by_name(name))
  # book => (<Book>)  
  # company => (<Company>) 
  

3 Responses to “Ruby Idiom: In-logic assignment”

Mislav Says: #

Yuk – parentheses!

Much better to use `and`:

if book = Book.find_by_title and company = Company.find_by_name

AQ Says: #

Well, you learn something everyday – I thought && was === and.

AQ: I believe there is a difference in precedence (in the order of operations for operators) between “and”/”or” and “&&”/”||”.

About

QuirkeyBlog is Aaron Quint's perspective on the ongoing adventure of Code, Life, Work and the Web.

twitter/@aq.

instagram/@quirkey.

github/quirkey.

QuirkeyBlog is proudly powered by WordPress

Categories