Copying an existing Ecto struct for insertion

196 views
Skip to first unread message

Thomas J.

unread,
Aug 27, 2020, 7:21:22 AM8/27/20
to elixir-ecto
A topic that comes back now and then, is how to copy an existing Ecto struct for insertion.

 
Simply removing the `:id` field is not sufficient, because the Ecto struct contains meta data (e.g. `:loaded`). I run into errors relating to function clauses not matching when trying to insert an existing Ecto struct, even when removing the `:id` ; pretty sure because of the meta data.

This is how I solve the problem in my application:

```
def duplicate(foo) do
  data =
     foo
     |> Map.take(Foo.__schema__(:fields))
     |> Map.delete(:id)

  struct(Foo, data)
end
```

That seems to work fine. But note how I have to rely on reflection in order to achieve that.

Question/proposition: do you think we can offer a function for copying an existing Ecto struct (to be inserted)?


José Valim

unread,
Aug 27, 2020, 7:44:54 AM8/27/20
to elixi...@googlegroups.com
We could add a new function to `Ecto`. The biggest question is how we would call it. :)

--
You received this message because you are subscribed to the Google Groups "elixir-ecto" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-ecto...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-ecto/84273e8a-9e98-4dcf-9365-2f78e39d4f06n%40googlegroups.com.

Thomas J.

unread,
Aug 27, 2020, 8:11:53 AM8/27/20
to elixir-ecto
That is indeed a problem 😁 However, I'd say `copy_new/1` (as in "copy into new entity")

Andrew Timberlake

unread,
Aug 27, 2020, 8:14:01 AM8/27/20
to elixi...@googlegroups.com
clone?

Andrew

Thomas J.

unread,
Aug 27, 2020, 8:16:08 AM8/27/20
to elixir-ecto
@Andrew for me the problem with copy/clone/duplicate/... is that it doesn't say that it becomes a new entity, that is, without the ID.

Hence I suggested to append `_new`

José Valim

unread,
Aug 27, 2020, 8:48:48 AM8/27/20
to elixi...@googlegroups.com
The issue about specifying semantics, such as copy or copy_new is that you also need to reason what happens with associations (are they also freshened up?) and we may not have a universal answer.

--


You received this message because you are subscribed to the Google Groups "elixir-ecto" group.


To unsubscribe from this group and stop receiving emails from it, send an email to elixir-ecto...@googlegroups.com.


Thomas J.

unread,
Aug 27, 2020, 9:00:22 AM8/27/20
to elixir-ecto
Could then the way of handling association be specified through options and a default value is documented?

`copy_new/2` with option `:on_association` that may have the values `:copy_new`, `:keep`, `:unload`.

(quick sketchy idea dump)

José Valim

unread,
Aug 27, 2020, 9:11:28 AM8/27/20
to elixi...@googlegroups.com
That could work, but it would have to be per association.

Further thoughts Regarding the name, I don’t like copy because every data change that we do in Elixir is a copy. It feels like we rather want to call it “erase_identity” or similar.

Adam Lancaster

unread,
Aug 27, 2020, 11:00:42 AM8/27/20
to elixi...@googlegroups.com
perhaps `new_from` or `build_from` ?

`build` is often what you see with factories for example, that build a struct but don’t put an id in it.

Best

Adam

Reply all
Reply to author
Forward
0 new messages