supabase-rb-rb
Database

Overview

PostgREST query builder, filters, modifiers, and RPC.

The database surface is the PostgREST query builder reachable through the top-level Supabase::Client. Every chain starts with supabase.from(table), then adds a verb (select / insert / update / upsert / delete), optional filters and modifiers, and ends with .execute to fire the request.

supabase = Supabase.create_client(
  supabase_url: ENV.fetch("SUPABASE_URL"),
  supabase_key: ENV.fetch("SUPABASE_ANON_KEY")
)

response = supabase
  .from("countries")
  .select("id, name")
  .eq("continent", "Africa")
  .order("name")
  .limit(20)
  .execute

response.data   # => [{ "id" => 1, "name" => "Algeria" }, ...]
response.count  # => nil unless you asked for count: "exact"

supabase.from returns a RequestBuilder; calling a verb returns a sub-builder that mixes in FilterMixin (every filter you'd expect from PostgREST) and, for select, SelectMixin (order / limit / offset / range). Nothing hits the wire until .execute.

Builders

MethodDescription
fromOpen a builder for a table. from_ and table are aliases.
selectRead rows. Accepts a column list, count:, and head:.
insertInsert one row (Hash) or many (Array<Hash>).
updatePatch rows that match the chained filters.
upsertInsert-or-update via Prefer: resolution=merge-duplicates.
deleteDelete rows that match the chained filters.
rpcCall a stored procedure (POST by default, GET / HEAD opt-in).
schemaSwitch the active Postgres schema. Returns a new client.

Filters

Filter methods are mixed into every verb builder. They mutate the request and return self so they chain. Every PostgREST operator is exposed.

MethodPostgREST operator
eqeq
neqneq
gtgt
gtegte
ltlt
ltelte
likelike
ilikeilike
like_all_oflike(all)
like_any_oflike(any)
ilike_all_ofilike(all)
ilike_any_ofilike(any)
is_is (null / true / false)
in_in
containscs
contained_bycd
overlapsov
range_lt / range_gt / range_gte / range_lte / range_adjacentsl / sr / nxl / nxr / adj
fts / plfts / phfts / wftsfull-text search variants
text_searchhigh-level FTS helper (sets type: / config:)
matcheq over every key in a Hash
or_grouped OR clause (reference_table: for joins)
not_negate the next filter
filterescape hatch — pass operator / criteria verbatim
max_affectedcap the number of rows a write may touch

Modifiers

Modifiers are added by SelectMixin. They apply to select (and rpc) builders.

MethodDescription
orderORDER BY column ASC/DESC. foreign_table: orders an embedded relation.
limitLIMIT n. foreign_table: limits an embedded relation.
offsetOFFSET n.
rangeInclusive start..finish (sets offset + limit).

Result-shape switchers

These live on the select builder and change how the response is parsed.

MethodDescription
singleExpect exactly one row; raise if the row count is not 1.
maybe_singleExpect 0 or 1 row; nil on 0, raise on more than 1.
csvReturn the body as CSV text instead of JSON.
explainReturn the PostgREST query plan instead of executing.

Executing a chain

Every builder returns from each step so you can keep chaining. The wire request only fires when you call .execute, which returns a Supabase::Postgrest::APIResponse with two readers:

  • data — the parsed JSON body (typically an Array<Hash>; Hash for single).
  • count — populated only when you opted in with count: "exact" | "planned" | "estimated".

A non-2xx response raises Supabase::Postgrest::Errors::APIError. The error carries :message, :code, :details, and :hint and accepts both string and symbol keys.

begin
  supabase.from("countries").select("*").eq("id", -1).single.execute
rescue Supabase::Postgrest::Errors::APIError => e
  e.code      # => "PGRST116" (no rows)
  e.message   # => "Cannot coerce the result to a single JSON object"
end

On this page