Hi,
It looks like Ecto prevents, by default, to change an association because on_update
is :raise
by default.
I naively changed my belongs_to
association and added on_update: :update
as suggested by the documentation but I now have another error:
Since you have set `:on_replace` to `:update`, you are only allowed
to update the existing entry by giving updated fields as a map or
keyword list or set it to nil.
If you indeed want to replace the existing :type, you have
to change the foreign key field directly.
I don’t really understand what that means because:
a) I pass my changes in a params
parameter that is a map
b) it looks Ecto is suggesting me to change the value directly by specifying the database column, which sounds awkward.
So I tried the latter and set the TYP_ID
column directly (ex: %{TYP_ID: 42}
) with the new id. This did work but that means I need to reference database columns directly from my controller code, which looks to be a bad practice in my opinion.
What code do I need to change the id of an association in a table? This is how I expected it to be done but did not work:
Persitance:
schema "upload" do
field :filename, :string, source: :UPL_FILENAME, size: 500
field :request_uuid, :string, source: :UPL_REQUEST_UUID, size: 100
field :status_code, :string, source: :UPL_STATUS_CODE, size: 50
belongs_to :type, Type, foreign_key: :TYP_ID, on_replace: :update
timestamps()
end
def changeset(%{status_code: status_code} = upload, params \\ %{}) do
upload
|> change(params)
|> cast(params, [:filename, :request_uuid, :status_code])
|> validate_required([:filename])
|> validate_required([:request_uuid])
|> validate_required([:status_code])
end
def save_upload(%Upload{} = upload, params \\ %{}) do
changeset(upload, params)
|> Repo.insert_or_update()
end
Insert or update:
upload =
Uploads.get_upload(String.to_integer(upload_id))
|> Repo.preload(:type)
updated_type = Uploads.get_type(new_type.id)
Upload.save_upload(upload, %{type: updated_type})
This code works when I update the first time (when the column is null) but not on subsequent updates. How can I handle this case with Ecto?
Thanks.