Ecto.Repo.insert_or_update

You're seeing just the callback insert_or_update, go back to Ecto.Repo module for more information.
Link to this callback

insert_or_update(changeset, opts)

View Source (optional)

Specs

insert_or_update(changeset :: Ecto.Changeset.t(), opts :: Keyword.t()) ::
  {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()}

Inserts or updates a changeset depending on whether the struct is persisted or not.

The distinction whether to insert or update will be made on the Ecto.Schema.Metadata field :state. The :state is automatically set by Ecto when loading or building a schema.

Please note that for this to work, you will have to load existing structs from the database. So even if the struct exists, this won't work:

struct = %Post{id: "existing_id", ...}
MyRepo.insert_or_update changeset
# => {:error, changeset} # id already exists

Options

  • :prefix - The prefix to run the query on (such as the schema path in Postgres or the database in MySQL). This overrides the prefix set in the query and any @schema_prefix set any schemas. Also, the @schema_prefix for the parent record will override all default @schema_prefixs set in any child schemas for associations.
  • :stale_error_field - The field where stale errors will be added in the returning changeset. This option can be used to avoid raising Ecto.StaleEntryError. Only applies to updates.
  • :stale_error_message - The message to add to the configured :stale_error_field when stale errors happen, defaults to "is stale". Only applies to updates.

See the "Shared options" section at the module documentation for more options.

Example

result =
  case MyRepo.get(Post, id) do
    nil  -> %Post{id: id} # Post not found, we build one
    post -> post          # Post exists, let's use it
  end
  |> Post.changeset(changes)
  |> MyRepo.insert_or_update

case result do
  {:ok, struct}       -> # Inserted or updated with success
  {:error, changeset} -> # Something went wrong
end