BrightEyesDavid

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

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"}

Where Next?

Popular in Questions Top

JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
greenz1
I have a phoenix application from which a user can download multiple(5-6) files of size 1MB. I couldn’t find anything related to sending ...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID&lt;0.412.0&gt; terminating ** (Postgrex.Error) FATAL...
New

Other popular topics Top

minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
AstonJ
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New

We're in Beta

About us Mission Statement