BrightEyesDavid
Using an Ecto result as params for a changeset
I have two schemas which are similar and which each contain the same embedded schema. One represents user-submitted data (submission) and one represents admin-created data which may or may not be based on a user submission (entry).
For entry’s new (from a submission) web admin action, so that the form inputs are prefilled with the submission’s data, how can I convert one Ecto submission result (a struct) and its embedded schemas (also structs) into a nested map in order to use it as params for a new changeset?
This would be from something like:
%MyApp.Submission{
__meta__: #Ecto.Schema.Metadata<:loaded, "submissions">,
entries: nil,
data: %MyApp.Data{
foo: true,
TemperatureData: [
%MyApp.Data.TemperatureOffset{
Offset: -3,
Temperature: -24,
id: "1ffd0e3f-d5d9-4d1e-9a99-ae190dddde08"
},
%MyApp.Data.TemperatureOffset{
Offset: 3,
Temperature: 10,
id: "7cd90b5b-19e1-4d4a-a68b-0d783ba76412"
}
],
id: "0b47e792-fc45-4c48-b476-877ede66aeda"
},
id: "0540750a-3ef3-4cf0-aa37-23cda4cb5d39",
name: "Test"
}
to:
%{
data: %{
HVT: true,
TemperatureData: [
%{
Offset: -3,
Temperature: -24
},
%{
Offset: 3,
Temperature: 10
}
]
},
id: "0540750a-3ef3-4cf0-aa37-23cda4cb5d39",
name: "Test"
}
(In the example result I’ve removed the embedded schema’s ids, though I’m not sure this is necessary.)
Thanks.
Edit: apologies - I’ve realised (I think) this can be achieved simply by using changeset functions. If I understand correctly, I just need to remove the submission’s id before using it to make a new changeset.
Most Liked
BrightEyesDavid
I currently have the following which seems to be doing the trick.
Controller:
def new(conn, %{"from_submission" => from_submission_id}) do
submission = WorkData.get_submission!(from_submission_id)
changeset = WorkData.create_entry_changeset_from_submission(submission)
# ...
end
Context:
def create_entry_changeset_from_submission(%Submission{} = submission) do
Entry.changeset_from_submission(submission)
end
Entry Schema:
def changeset_from_submission(submission) do
%Entry{}
|> changeset(%{})
|> put_change(:data, submission.data)
|> put_change(:type, submission.type)
|> put_change(:name, submission.name)
end
Does this seem like a sane/reasonable way of creating a changeset in order to prefill entry HTML form fields with values from a submission?
It avoids what I get when I try to throw the whole single submission result into a changeset, even after using Map.from_struct/1:
[debug] ** (Ecto.CastError) expected params to be a :map, got: %MyApp.MyModule.WorkData.TemperatureOffsetProfile{foo: true, TemperatureData: [%MyApp.MyModule.WorkData.TemperatureOffset{Offset: -3, Temperature: -24, id: "1ffd0e3f-d5d9-4d1e-9a99-ae190dddde08"}, %MyApp.MyModule.WorkData.TemperatureOffset{Offset: 3, Temperature: 10, id: "7cd90b5b-19e1-4d4a-a68b-0d783ba76412"}], id: "0b47e792-fc45-4c48-b476-877ede66aeda"}
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
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex









