That have the exactly same logic with the additional issue that creation functions call insertion functions. So let’s deep dive on this issue:
Semantics
Following Phoenix context and Ecto semantics, insertion function should receive the already built struct of the schema OR a %Ecto.Changeset{} that represents the current schema via the data attribute.
On the other hand, creation functions should receive raw parameters as maps, trigger the changeset function to parse this parameter and then leverage the insertion function.
There’s no idea of “creation” on Ecto.Repo, as it leverages direct database API functions.
What’s on currently?
Currently the insertion and creation functions have the exactly same logic, as:
builds a struct from __MODULE__, passes it to the changeset function and then to the local insert function
Proposal
I would like to make a suggestion:
insertion functions would receive the already built struct or a changeset of the same schema (to match the library concept), something like:
@impl SwissSchema
def insert(source, opts \\ [])
def insert(%Ecto.Changeset{data: %mod{}} = changeset, opts) do
case mod do
MODULE -> performinsert(changeset, opts)
-> {:error, :not_same_schema_module}
end
end
def insert(%mod{} = struct, opts) when is_struct(struct) do
case mod do
MODULE -> performinsert(struct, opts)
-> {:error, :not_same_schema_module}
end
end
defp perform_insert(source, opts) do
repo = Keyword.get(opts, :repo, unquote(
insert = Function.capture(repo, :insert, 2)
insert.(source, opts)
end
2. creation functions would do the same logic as now, no need to change this api.
Currently we define:
insert/2
insert!/2
create/2
create!/2
That have the exactly same logic with the additional issue that creation functions call insertion functions. So let’s deep dive on this issue:
Semantics
Following Phoenix context and Ecto semantics, insertion function should receive the already built struct of the schema OR a
%Ecto.Changeset{}
that represents the current schema via thedata
attribute.On the other hand, creation functions should receive raw parameters as maps, trigger the
changeset
function to parse this parameter and then leverage the insertion function.There’s no idea of “creation” on
Ecto.Repo
, as it leverages direct database API functions.What’s on currently?
Currently the insertion and creation functions have the exactly same logic, as:
repo
insert/2
function from therepo
changeset/2
function__MODULE__
, passes it to the changeset function and then to the local insert functionProposal
I would like to make a suggestion:
def insert(%Ecto.Changeset{data: %mod{}} = changeset, opts) do case mod do MODULE -> performinsert(changeset, opts) -> {:error, :not_same_schema_module} end end
def insert(%mod{} = struct, opts) when is_struct(struct) do case mod do MODULE -> performinsert(struct, opts) -> {:error, :not_same_schema_module} end end
defp perform_insert(source, opts) do repo = Keyword.get(opts, :repo, unquote( insert = Function.capture(repo, :insert, 2) insert.(source, opts) end