Home Blog Understanding find_sole_by in Rails
Ruby on Rails

Understanding find_sole_by in Rails

Sep 16, 2025
Understanding find_sole_by in Rails

Rails has a long history of providing expressive, intuitive query methods. You’re probably familiar with find_by and find_by!, which let you grab records by certain attributes. But since Rails 6.0, a newer method has joined the Active Record toolbox: find_sole_by.

It looks deceptively similar to find_by, but it behaves quite differently—and more strictly. In this post, we’ll break down what it does, why it exists, and when you should use it.

A Refresher: find_by vs. find_by!

Before diving in, let’s quickly review:

  • find_by: Returns the first record that matches the given conditions. If no record is found, it returns nil.
  • find_by!: Same as above, but raises ActiveRecord::RecordNotFound if no record is found.

Both of these methods are fine when you don’t mind multiple rows potentially matching the query. But what if you want to enforce uniqueness at query time, not just in your model validations?

Enter find_sole_by

find_sole_by is like find_by! but stricter. It ensures:

  1. Exactly one record matches the conditions.
  2. If no records match, it raises ActiveRecord::RecordNotFound.
  3. If multiple records match, it raises ActiveRecord::SoleRecordExceeded.

That’s right—it enforces sole-ness.

Example:

# Suppose users have a unique email
User.find_sole_by(email: "[email protected]")
# => returns the single record

User.find_sole_by(email: "[email protected]")
# => raises ActiveRecord::RecordNotFound

User.find_sole_by(role: "admin")
# => raises ActiveRecord::SoleRecordExceeded if more than one admin exists

Why Would You Use It?

There are several scenarios where find_sole_by is a better fit than find_by:

  • Enforcing assumptions in code: If your application logic assumes there will only ever be one matching record, find_sole_by ensures that assumption holds true in the database.
  • Preventing silent bugs: find_by will quietly return the first record if multiple exist, which can lead to confusing, hard-to-track issues. find_sole_by forces you to deal with duplicates immediately.
  • Safer domain modeling: Even if you have validations or unique indexes, database drift and data corruption can happen. This method adds another safeguard.

Comparing All Four Methods

MethodNo MatchOne MatchMultiple Matches
find_bynilrecordfirst record found (not guaranteed)
find_by!raises RecordNotFoundrecordfirst record found (not guaranteed)
find_sole_byraises RecordNotFoundrecordraises SoleRecordExceeded
find_sole_by!⚠️doesn’t exist (use find_sole_by)--

A Real-World Example

Imagine you’re building a tournament app. A Tourney might have a single “final match” you want to fetch. You know there must be exactly one match with round: “final”.

tourney.matches.find_sole_by(round: "final")

This guarantees you don’t accidentally fetch the wrong match if multiple finals exist—or a nil if one hasn’t been created yet. Your code will blow up loudly instead of failing silently.

Takeaways

  • Use find_by if multiple matches are acceptable, and you’re fine with nil when none exist.
  • Use find_by! if multiple matches are acceptable, but you want to enforce at least one match.
  • Use find_sole_by when your domain logic requires exactly one record.

In short: find_sole_by helps you write safer, more intentional queries.

Ruby on Rails