supabase-rb-rb
Database

Update data

Patch rows that match the chained filters.

Patch existing rows via PATCH. Pass a Hash of column-value updates, chain at least one filter to scope which rows are touched, then call .execute. Updates with no filter are rejected by PostgREST unless you've used max_affected to opt in explicitly.

Signature

supabase.from(table).update(json, count: nil, returning: "representation")

Parameters

NameTypeRequiredDescription
jsonHashRequiredMap of column → new value. Columns omitted from the Hash are left alone. Nested JSONB values can be patched by passing the whole new JSON object — partial JSONB merges are not supported by PostgREST.
countStringOptionalOne of "exact", "planned", "estimated". Adds Prefer: count=... so APIResponse#count is populated from the Content-Range header.
returningStringOptional"representation" (default) returns the updated rows; "minimal" returns no body, which is faster for fire-and-forget writes.

Returns

Returns
Supabase::Postgrest::FilterRequestBuilder

A chainable builder that mixes in FilterMixin — chain filters to scope the update, then call .execute to fire the request and receive an APIResponse.

Example — update a single row by primary key

response = supabase
  .from("countries")
  .update(name: "Türkiye")
  .eq("id", 99)
  .execute

response.data  # => [{ "id" => 99, "name" => "Türkiye", ... }]

Example — bulk update with a compound filter

response = supabase
  .from("orders")
  .update(status: "shipped", shipped_at: Time.now.utc.iso8601)
  .eq("status", "ready_to_ship")
  .lte("created_at", "2026-06-01")
  .execute

response.data.length  # => however many rows matched

Example — fire-and-forget update

returning: "minimal" returns no body, so data is []. Use this when you don't need the updated rows back.

supabase
  .from("audit_log")
  .update(seen: true, returning: "minimal")
  .eq("user_id", 42)
  .execute

Example — count the affected rows

response = supabase
  .from("orders")
  .update({ archived: true }, count: "exact")
  .eq("status", "completed")
  .execute

response.count  # => N rows updated

Example — guard a bulk update with max_affected

max_affected(N) adds Prefer: handling=strict,max-affected=N. PostgREST refuses the update (returning 400) if the row count would exceed N. This is the safe way to issue an unfiltered-looking update.

supabase
  .from("invoices")
  .update(due_at: nil)
  .eq("status", "voided")
  .max_affected(50)
  .execute

Updates with no filters do NOT silently update every row — PostgREST refuses the request unless max_affected has explicitly opted in.

On this page