Skip to content

Latest commit

 

History

History
49 lines (37 loc) · 1.73 KB

empty-find-by-returns-first-record.md

File metadata and controls

49 lines (37 loc) · 1.73 KB

Empty find_by Returns First Record

During a RubyConf 2024 talk, a speaker mentioned that if you pass nil to ActiveRecord's #find_by method, it will return the first record from the database. This is a bit unintuitive, so lets look at an example and then I'll show you why.

> Book.first
#=> #<Book:0x00000001142e4c48 id: 13, title: "The Secret History", ... >

> Book.find_by(nil)
#=> #<Book:0x00000001142ca3c0 id: 13, title: "The Secret History", ... >

So, that is the same object in both cases, but why?

Our first hint is in the SQL that gets constructed when making that method call.

Book Load (2.5ms)  SELECT "books".* FROM "books" LIMIT $1  [["LIMIT", 1]]

It's grabbing all books and limiting to one result.

Lets look at the underlying implementation of the #find_by method.

# File activerecord/lib/active_record/relation/finder_methods.rb, line 111
def find_by(arg, *args)
  where(arg, *args).take
end

Sure enough, the implementation is a #where followed by a #take. Since the #where is receiving nil as its arg, there are no conditions filtering the query. And the #take corresponds to the limit 1.

Knowing that, we can understand that we will also get the first record from the database if we call #find_by with {}. Again, no conditions to filter on, so give me all books limited to one.

One small caveat: notice how there is no order by clause in the above SQL output. This differs from Books.first which implicitly does an order on the id column. Though these method are likely to return the same result, the ordering of #find_by is not guaranteed to be the same without an order by clause.