Sometimes learning to code feels like a game of Marco Polo. I’m swimming in a pool of methods trying to find the right one. Though in this post I’ll lift the blindfold and expose the difference between the .find
and the .find_by
Active Record methods.
The .find and .find_by_id methods both search for an object in the database that matches an ID in the argument. The .find_by method also does the same search when the argument is ID. So in an effort to keep the code DRY and as minimal as possible, your initial coding instinct might be to use the .find
method if you are searching by ID. What happens if the record matching the ID isn’t found? This is where we take a look behind the scenes and shine a spotlight on the differences between these methods.
When calling the .find
method with the argument of an ID that isn’t in the database, Active Record will raise a RecordNotFound error. This method assumes there is definitely an object with the ID you ask for. So if it finds the object, then it returns the object, which is great! If it doesn’t find it, you’ll get an error, which isn’t really helpful in an if
statement to handle a case where it doesn’t find the ID you asked for. For instance in a music app index, if a user searches for an artist based on their ID, they could see all the songs by that particular artist. If the artist couldn’t be found, you might want to let the user know and redirect them to see all artists. Here’s the code:
I use the .find_by
method here because the if statement depends on its return value. It either finds the record of the artist, or it will return nil. If the artist can’t be found, returning nil is what we need in order to execute the else statement. Alternatively the .find
method would throw an error and it wouldn’t reach the else statement. The .find_by_id
method also gets the tests passing in Rails v4.2.5 but it appears to be deprecated and isn’t standard practice anymore.
Although DRY is generally a great principle to code by, sometimes lengthier, more explicit code saves the day.
TL;DR: In the case of a music app search, Artist.find_by(id: params[:id])
wins in comparison to Artist.find(params[:id])
because the .findby method returns nil if it’s not found, and the .find method raises an error if it’s not found.
For more information on DRY vs. WET code:
For more information on the difference between these methods: