Retrieve zero or one rows
Expect 0 or 1 row. Returns nil on no match; raises only when more than 1 row comes back.
Soft variant of single. Lives on the select builder. Unlike single, the SELECT-chain maybe_single does not set the vnd.pgrst.object+json Accept header — the request goes out expecting an array, and the client inspects the result:
- 0 rows →
.executereturnsnil(not a response object). - 1 row →
.executereturns aSingleAPIResponsewith the row as aHash. - more than 1 row → raises
Supabase::Postgrest::Errors::APIErrorwith the message"Cannot coerce the result to a single JSON object".
Pick maybe_single whenever "no row" is a valid case in your domain — it's the friendlier shape for optional lookups.
Signature
builder.maybe_singleParameters
This method has no parameters.
Returns
A builder that, when .execute'd, returns nil (no row), a SingleAPIResponse (one row, data is a Hash), or raises an APIError (more than one row).
Example — optional lookup
response = supabase
.from("users")
.select("id, email")
.eq("email", "alice@example.com")
.maybe_single
.execute
if response.nil?
puts "no such user"
else
response.data # => { "id" => 7, "email" => "alice@example.com" }
endExample — guard a >1 accident
If multiple rows match (the filter is not unique), .execute raises:
begin
supabase
.from("countries")
.select("*")
.eq("continent", "Africa") # many rows
.maybe_single
.execute
rescue Supabase::Postgrest::Errors::APIError => e
e.message # => "Cannot coerce the result to a single JSON object"
endIf you don't want any >1 guard, drop maybe_single and call .execute directly — you'll get the array of rows.
maybe_single vs single
maybe_single | single | |
|---|---|---|
Sets Accept: application/vnd.pgrst.object+json | no (SELECT chain) | yes |
| 0 rows | .execute returns nil (no exception) | raises APIError (PGRST116) |
| 1 row | data is the row as a Hash | data is the row as a Hash |
| more than 1 row | raises APIError ("Cannot coerce…") — client-side check | raises APIError (PGRST116) — server-side |
| Use when | the row may or may not exist (optional lookup) | the row must exist (PK lookup) |
The single most user-visible difference: with single, a missing row is an exception you must rescue; with maybe_single, it's a nil you can branch on.
maybe_single does not set the object Accept header on SELECT chains
The SELECT-chain maybe_single deliberately omits the vnd.pgrst.object+json Accept header (the RPC variant does set it). This asymmetry is intentional — not a bug.