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>)
Yuk – parentheses!
Much better to use `and`:
if book = Book.find_by_title and company = Company.find_by_name
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 “&&”/”||”.