I have this schema:
defmodule Pescarte.Domains.ModuloPesquisa.Models.Midia do
use Pescarte, :model
alias Pescarte.Domains.Accounts.Models.User
alias Pescarte.Domains.ModuloPesquisa.Models.Midia.Tag
@type t :: %Midia{
id: integer,
tipo: atom,
nome_arquivo: binary,
data_arquivo: Date.t(),
restrito?: boolean,
observacao: binary,
link: binary,
texto_alternativo: binary,
id_publico: binary,
autor: User.t(),
tags: list(Tag.t())
}
@required_fields ~w(tipo nome_arquivo data_arquivo link autor_id)a
@optional_fields ~w(observacao texto_alternativo restrito?)a
@tipos ~w(imagem video documento)a
schema "midia" do
field :tipo, Ecto.Enum, values: @tipos
field :nome_arquivo, :string
field :data_arquivo, :date
field :restrito?, :boolean, default: false
field :observacao, :string
field :link, :string
field :texto_alternativo, :string
field :id_publico, :string
belongs_to :autor, User, on_replace: :update
many_to_many :tags, Tag,
join_through: "midias_tags",
on_replace: :delete,
unique: true
timestamps()
end
@spec changeset(Midia.t(), map, list(Tag.t())) :: {:ok, Midia.t()} | {:error, changeset}
def changeset(%__MODULE__{} = midia, attrs, tags \\ []) do
midia
|> cast(attrs, @required_fields ++ @optional_fields)
|> validate_required(@required_fields)
|> unique_constraint(:link)
|> unique_constraint(:nome_arquivo)
|> foreign_key_constraint(:autor_id)
|> put_assoc(:tags, tags)
|> put_change(:id_publico, Nanoid.generate())
|> apply_action(:parse)
end
def tipos, do: @tipos
end
And I want to create an upsert
function for this schema, tried to do:
defmodule Pescarte.Domains.ModuloPesquisa.MidiaRepository do
alias Pescarte.Domains.ModuloPesquisa.IManageRepository
alias Pescarte.Domains.ModuloPesquisa.Models.Midia
alias Pescarte.Repo
@behaviour IManageRepository
# ...
@impl true
def upsert(attrs) do
with {:ok, midia} <- Midia.changeset(attrs) do
Repo.insert(midia, on_conflict: {:replace_all_except, [:id]}, conflict_target: [:link])
end
end
# ...
end
That should work fine for new entries where I pass an attrs
map. But how about an existing %Midia{}
? How can I pass it to the changeset without lose not casted field like id
primary key?
I’ts not possible to call changeset/3
as
Midia.changeset(%Midia{id: "existing"}, %Midia{id: "existing", link: "new link"})
Does it make sense?