Softknobs
How to update a belongs_to association?
Hi,
It looks like Ecto prevents, by default, to change an association because on_update is :raiseby 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.
Most Liked
thojanssens1
Yes definitely. cast/4 creates a changeset from untrusted data (user input). You call change/2 for creating a changeset from trusted/internal data. You use either one or the other for transforming the params into a changeset. Here I suppose the parameters received are untrusted, so you just need to use cast/4. This doesn’t answer your question but that’s a first issue in the code:)
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









