Current section
Files
Jump to
Current section
Files
lib/repo_base.ex
defmodule EctoForge.DatabaseApi do
alias EctoForge.Utls.ExecuteExtensionEvents
defmacro __using__(opts) do
quote location: :keep, bind_quoted: [opts: opts] do
@module_model opts[:module_model] || __MODULE__
@doc """
## Базовые функции для модели `#{@module_model}`
## Example
```elixir
iex> #{@module_model}.get_all(
type_private: :public
)
```
"""
@repo opts[:repo]
@extensions_events opts[:extensions_events]
@ignore_fields opts[:ignore_fields] || []
@extensions_get opts[:extensions_get] || []
@not_found_message opts[:error_message] || :not_found
use EctoForge.Helpers.QueryBinderGet,
repo: @repo,
extensions_get: opts[:extensions_get],
module_model: @module_model
@doc """
## Создает и делает insert структуры по дефолту дергает функцию changeset из `#{@module_model}`
Возвращает `{:ok, item}` или `{:error, error_changeset}`
## Example
```
#{@module_model}.create(%{name: "artem"})
```
"""
def create(map) do
map = ExecuteExtensionEvents.exucute_before_created(map, @extensions_events)
@module_model.changeset(%@module_model{}, map)
|> @repo.insert()
|> ExecuteExtensionEvents.exucute_after_created(@extensions_events)
end
@doc """
## Создает и делает insert структуры, вместе функцией changeset
Возвращает `{:ok, item}` или `{:error, error_changeset}`
## Example
```
#{@module_model}.create(%{name: "artem"}, :changeset_register)
```
"""
def create(map, function) do
map = ExecuteExtensionEvents.exucute_before_created(map, @extensions_events)
apply(@module_model, function, [map])
|> @repo.insert()
|> ExecuteExtensionEvents.exucute_after_created(@extensions_events)
end
@doc """
## Создает и делает insert структуры по дефолту дергает функцию changeset из `#{@module_model}`
Возвращает `{:ok, item}` или `{:error, error_changeset}`
## Example
```
#{@module_model}.create(%{name: "artem"})
```
"""
def create!(map) do
map = ExecuteExtensionEvents.exucute_before_created!(map, @extensions_events)
@module_model.changeset(%@module_model{}, map)
|> @repo.insert!()
|> ExecuteExtensionEvents.exucute_after_created!(@extensions_events)
end
@doc """
## Создает и делает insert структуры, вместе функцией changeset
Возвращает `{:ok, item}` или `{:error, error_changeset}`
## Example
```
#{@module_model}.create(%{name: "artem"}, :changeset_register)
```
"""
def create!(map, function) do
map = ExecuteExtensionEvents.exucute_before_created!(map, @extensions_events)
res =
apply(@module_model, function, [map])
|> @repo.insert!()
|> ExecuteExtensionEvents.exucute_after_created!(@extensions_events)
end
@doc """
# Возвращает все поля в scheme
## Example
```
iex> #{@module_model}.fields()
[:id, :name]
```
## Можно фильтровать значения которые не нужны
```
iex> #{@module_model}.fields([:id])
[:name]
```
"""
def fields(filtered \\ []) when is_list(filtered) do
schema = @module_model.__schema__(:fields)
if filtered != [] do
schema
|> Enum.filter(fn x ->
!(x in filtered)
end)
else
schema
end
end
@doc """
Возвращает структуру по ее id или по соответствию значения полей структуры
"""
def find(opts) when is_list(opts) or is_map(opts) do
try do
query_bindings(opts, :one)
rescue
Ecto.Query.CastError -> nil
end
|> get_helper_after
end
def find(item_id) do
try do
query_bindings([id: item_id], :all)
rescue
Ecto.Query.CastError -> nil
end
|> get_helper_after
end
@doc """
## Возвращает структуру по ее id или по соответствию значения полей структуры
## Example
```
#{@module_model}.get(
type_private: :public,
)
```
"""
def get(item_id_or_opts) do
case find(item_id_or_opts) do
%@module_model{} = item -> {:ok, item}
nil -> {:error, @not_found_message}
end
end
@doc """
## Возвращает структуру по ее id или по соответствию значения полей структуры либо выдает ошибку `Ecto.NoResultsError`
## Example
```
#{@module_model}.get!(
type_private: :public,
)
```
"""
def get!(item_id_or_opts) do
case find(item_id_or_opts) do
%@module_model{} = item -> item
nil -> throw(%Ecto.NoResultsError{message: "#{inspect(%@module_model{})} not found"})
end
end
@doc """
## Получает или добавляет запись если не найдена
## Example
```
#{@module_model}.get_or_insert(%{user_id: ""}, %{login: "12", password: "1234"})
```
"""
def get_or_insert(attrs_get, attrs_create) do
case get(attrs_get) do
{:ok, user} -> {:ok, user}
{:error, _} -> create(attrs_create)
end
end
def exists?(opts) when is_list(opts) or is_map(opts) do
get!(opts)
|> @repo.exists?()
end
@doc """
## Возвращает список всех имеющихся структур или по соответствию значения полей структуры
## Самое главное что нужно понять
В get_all можно передать map или keyword list все будет попадать where
#{@module_model}.get_all(%{status: 1})
будет приравниваться `#{@module_model}|> where(%{status: 1)`
#{@module_model}.get_all(%{preload: [:user]})
будет приравниваться `#{@module_model}|> preload( [:user])`
## Example
```
#{@module_model}.get_all(
type_private: :public,
)
```
"""
def find_all(opts \\ nil) do
try do
query_bindings(opts, :all)
rescue
Ecto.Query.CastError -> []
end
|> get_helper_after
end
@doc """
## Возвращает список всех имеющихся структур или по соответствию значения полей структуры
"""
def get_all(opts \\ nil) do
case find_all(opts) do
[] -> {:error, @not_found_message}
items -> {:ok, items}
end
end
@doc """
## Вовзращает либо ошибку либо результат выполнения find_all
## Example
```
#{@module_model}.get_all!(
type_private: :public,
)
```
"""
def get_all!(item_id_or_opts \\ nil) do
case find_all(item_id_or_opts) do
[] -> throw(%Ecto.NoResultsError{message: "#{inspect(%@module_model{})} not found"})
items -> items
end
end
@doc """
## Обновление структуры вместе с другим changeset
iex -> update_with_another_changeset(#{@module_model}, %{update_attrs: ""}, :function_in_changeset)
третий аргумент функция которая находиться в модуле
"""
def update_with_another_changeset(%@module_model{} = item, opts, function_atom, attrs \\ [])
when is_atom(function_atom) do
res =
apply(@module_model, function_atom, [item, opts])
|> @repo.update(attrs)
end
@doc """
## Обновление структуры вместе с другим changeset выкидывает throw
iex -> update_with_another_changeset!(#{@module_model}, %{update_attrs: ""}, :function_in_changeset)
третий аргумент функция которая находиться в модуле
"""
def update_with_another_changeset!(
%@module_model{} = item,
opts,
function_atom,
attrs \\ []
)
when is_atom(function_atom) do
res =
apply(@module_model, function_atom, [item, opts])
|> @repo.update!(attrs)
end
@doc """
## Обновляет запись по item, %{}
iex -> update(#{@module_model}, %{update_attrs: ""}, repo.update)
"""
def update(%@module_model{} = item, opts, attrs \\ []) do
res =
item
|> @module_model.changeset(EctoForge.Helpers.RepoBase.Utls.MapUtls.opts_to_map(opts))
|> @repo.update(attrs)
end
@doc """
## Обновляет запись по item, %{}, выкидывает исключение
iex -> `update!(#{@module_model}, %{update_attrs: ""}, repo.update)`
"""
def update!(%@module_model{} = item, opts, attrs \\ []) do
res =
item
|> @module_model.changeset(EctoForge.Helpers.RepoBase.Utls.MapUtls.opts_to_map(opts))
|> @repo.update!(attrs)
end
@doc """
## Получает структуру c помощью #{@module_model}.get(get_opts) и обновляет
iex -> update_by_opts(#{@module_model} %{update_attrs: "asd"}, []) третий параметр для
## Возвращает
{:ok, _}
{:error, _}
"""
def update_by_opts(get_opts, update_opts, attrs \\ []) do
res =
with {:ok, item} <- get(get_opts),
{:ok, item} <- update(item, update_opts, attrs) do
{:ok, item}
end
end
@doc """
## Получает структуру c помощью #{@module_model}.get(get_opts) и обновляет
iex -> update_by_opts(#{@module_model} %{update_attrs: "asd"}, []) третий параметр для
"""
def update_by_opts!(get_opts, update_opts, attrs \\ []) do
res =
get!(get_opts)
|> update!(update_opts, attrs)
end
@doc """
## Удаляет запись по id, item, #{@module_model} или map
## Возвращает
{:ok, _}
{:error, _}
"""
def delete(%@module_model{} = item) do
item = ExecuteExtensionEvents.exucute_before_deleted(item, @extensions_events)
try do
@repo.delete(item)
|> ExecuteExtensionEvents.exucute_after_deleted(@extensions_events)
rescue
err -> {:error, err}
end
end
def delete!(%@module_model{} = item) do
ExecuteExtensionEvents.exucute_before_deleted!(item, @extensions_events)
res =
@repo.delete!(item)
|> ExecuteExtensionEvents.exucute_after_deleted!(@extensions_events)
end
@doc """
## получает структуру и удаляет ее с помощью функций #{@module_model}.get(%{}) |> #{@module_model}.delete
"""
def delete!(item_id_or_opts) when is_map(item_id_or_opts) or is_binary(item_id_or_opts) do
get!(item_id_or_opts)
|> delete!()
end
@doc """
## получает структуру и удаляет ее с помощью функций #{@module_model}.get(%{}) |> #{@module_model}.delete
"""
def delete(item_id_or_opts) do
with {:ok, item} <- get(item_id_or_opts),
{:ok, item} <- delete(item) do
{:ok, item}
end
end
defp get_helper_after(result) do
case result do
{:ok, item} ->
ExecuteExtensionEvents.exucute_after_get(item, @extensions_events)
{:error, _} ->
result
[] ->
result
nil ->
result
result ->
ExecuteExtensionEvents.exucute_after_get(result, @extensions_events)
end
end
end
end
end