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.