Current section

Files

Jump to
ecto3_mnesia lib ecto adapters mnesia record.ex
Raw

lib/ecto/adapters/mnesia/record.ex

defmodule Ecto.Adapters.Mnesia.Record do
@moduledoc false
alias Ecto.Adapter.Schema
alias Ecto.Adapters.Mnesia
alias Ecto.Adapters.Mnesia.Source
@type t :: tuple()
# new api
@spec new(tuple() | Keyword.t() | map() | Ecto.Schema.t(), Source.t()) :: t()
def new(data, source) when is_tuple(data) do
Tuple.insert_at(data, 0, source.record_name)
end
def new(%{__struct__: _} = struct, source) do
struct
|> Map.from_struct()
|> Map.drop([:__meta__])
|> Enum.map(fn {field, value} -> {source.schema.__schema__(:field_source, field), value} end)
|> new(source)
end
def new(data, source) when is_list(data) or is_map(data) do
pattern = source.default
update(pattern, data, source)
end
# new api
@spec update(t(), Enumerable.t(), Source.t(), [atom()] | :all) :: t()
def update(record, params, source, replace \\ :all) do
params
|> Enum.reduce(record, fn {field, value}, acc ->
if replace == :all or Enum.member?(replace, field) do
case source.index[field] do
nil ->
# Association or virtual field
acc
field_index ->
acc
|> put_elem(field_index, value)
|> maybe_update_key(field, field_index, source)
end
else
acc
end
end)
end
# new api
@spec select(t(), [atom()], Source.t()) :: Schema.fields()
def select(record, fields, %{index: index}) do
Enum.map(fields, &{&1, elem(record, index[&1])})
end
def select_all(record, %{index: index, attributes: attributes}) do
Enum.map(attributes, &{&1, elem(record, index[&1])})
end
@spec to_schema(t(), Source.t()) :: Ecto.Schema.t()
def to_schema(record, %{loaded: loaded, index: index, source_field: fields}) do
index
|> Enum.reduce(loaded, fn {field, i}, acc ->
Map.put(acc, fields[field], elem(record, i))
end)
end
@spec gen_id(Keyword.t(), Source.t()) :: Keyword.t()
def gen_id(params, source) do
case source.autogenerate_id do
nil ->
params
{_schema_key, source_key, type} ->
if params[source_key] do
params
else
merge_autogen_params(params, source.table, source_key, type)
end
end
end
###
### Priv
###
defp maybe_update_key(record, _field, _field_index, %{extra_key: nil}),
do: record
defp maybe_update_key(record, field, field_index, %{extra_key: extra_key}) do
case Map.fetch(extra_key, field) do
{:ok, key_index} ->
record
|> elem(1)
|> case do
:_ ->
# Ignore record pattern
record
key ->
key = put_elem(key, key_index, elem(record, field_index))
put_elem(record, 1, key)
end
:error ->
record
end
end
defp merge_autogen_params(params, table, key, :id) do
Keyword.put(params, key, Mnesia.next_id(table, key))
end
defp merge_autogen_params(params, _table, key, :binary_id) do
Keyword.put(params, key, Ecto.UUID.generate())
end
end