supabase-rb-rb
Database

Insert data

Insert one row (Hash) or many (Array<Hash>) into a table.

Insert one or many rows into a table. The first argument can be a single Hash (single-row insert) or an Array<Hash> (bulk insert — PostgREST infers the column list from the first row's keys).

Signature

supabase.from(table).insert(json, count: nil, returning: "representation", upsert: false, default_to_null: true)

Parameters

NameTypeRequiredDescription
jsonHash or Array<Hash>RequiredRow payload. A Hash inserts one row; an Array<Hash> bulk-inserts. For bulk inserts PostgREST takes the column list from the union of the rows hash keys.
countStringOptionalOne of "exact", "planned", "estimated". Adds Prefer: count=... so APIResponse#count is populated from the Content-Range header.
returningStringOptional"representation" (default) returns the inserted rows; "minimal" returns no body, which is faster for fire-and-forget writes.
upsertBooleanOptionalWhen true, adds Prefer: resolution=merge-duplicates so a primary-key/unique conflict overwrites the existing row instead of failing. Prefer the dedicated upsert builder if you need the full upsert vocabulary (on_conflict, ignore_duplicates).
default_to_nullBooleanOptionalWhen false, adds Prefer: missing=default so columns missing from the payload fall back to their column DEFAULT instead of NULL. Useful for bulk inserts where rows have differing key sets.

Returns

Returns
Supabase::Postgrest::QueryRequestBuilder

A chainable builder. Call .execute to fire the request and receive an APIResponse (data: lists the inserted rows when returning: "representation").

Example — insert a single row

response = supabase
  .from("countries")
  .insert(name: "Wakanda", continent: "Africa")
  .execute

response.data  # => [{ "id" => 250, "name" => "Wakanda", "continent" => "Africa" }]

Example — bulk insert

Pass an Array<Hash> to insert many rows in one request. PostgREST collects the column list from the union of every row's keys; rows missing a key receive NULL (or the column default — see default_to_null:).

response = supabase
  .from("countries")
  .insert([
    { name: "Wakanda", continent: "Africa" },
    { name: "Genosha", continent: "Africa" },
    { name: "Latveria", continent: "Europe" }
  ])
  .execute

response.data.length  # => 3

Example — fire-and-forget (no body back)

returning: "minimal" returns no body, so data is []. Use this when you don't need the inserted row(s) and want to skip the serialization cost.

supabase
  .from("audit_log")
  .insert({ event: "login", user_id: 42 }, returning: "minimal")
  .execute

# response.data => []

Example — count without representation

response = supabase
  .from("countries")
  .insert([{ name: "Wakanda" }, { name: "Genosha" }], count: "exact")
  .execute

response.count  # => 2

Example — insert + chained select

select after insert flips the Prefer header to return=representation (overriding returning:) and adds a select= query parameter so you can shape the response.

response = supabase
  .from("countries")
  .insert(name: "Wakanda")
  .select("id, name")
  .execute

response.data  # => [{ "id" => 250, "name" => "Wakanda" }]

Types::ReturnMethod::REPRESENTATION / ::MINIMAL are the constants behind the string values for returning:.

On this page