1player
Idiomatic way to duplicate an Ecto.Changeset
In my CRUD app I would like to add a duplicate feature, in which an existing object’s data is used to prepopulate the form. The naive way I started with was:
def duplicate(conn, %{"id" => item_id}) do
item = Repo.get!(Item, item_id)
changeset = Ecto.Changeset.change(item)
render(conn, "new.html", changeset: changeset)
end
where new.html renders a form with form_for pointing to the POST method.
BUT this does not work, as phoenix_ecto overrides the POST method in the form by setting the hidden _method field to put, because it’s noticed that the changeset refers to an existing item in the database, as shown here: phoenix_ecto/lib/phoenix_ecto/html.ex at main · phoenixframework/phoenix_ecto · GitHub
What is the idiomatic way of duplicating a Changeset that refers to an actual record, so that a new entry is created, without having to manually remove the __meta__ field from the changeset?
Most Liked
al2o3cr
I suspect any function on Ecto.Changeset is going to wind up doing things you don’t want - in this case, I’d recommend taking the simplest possible route and writing a function in Item that takes an Item and returns an unsaved Ecto.Changeset:
def duplicate(item) do
changeset(%Item{}, %{title: item.title})
end
Reasoning:
-
you likely don’t want to copy some fields (ID, naturally; also probably
inserted_atetc) -
you might want to modify specific data - for instance, adding " (copy)" or similar to a title
-
you may need to do additional work to copy some fields (
has_manyassociations, for instance)
LostKobrakai
Unset the id (or any other primary key) for the item and it’s essentially a unsaved copy.
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









