defmodule MishkaInstaller.Setting do @moduledoc """ This module is for communication with `Settings` table and has essential functions such as adding, editing, deleting, and displaying. This module is related to module `MishkaInstaller.Database.SettingSchema`. """ alias MishkaInstaller.Database.SettingSchema import Ecto.Query use MishkaDeveloperTools.DB.CRUD, module: SettingSchema, error_atom: :setting, repo: MishkaInstaller.repo() @behaviour MishkaDeveloperTools.DB.CRUD @doc """ If you want to get the latest changes from the `Settings` table of your database, this function can help you to be subscribed. """ def subscribe do Phoenix.PubSub.subscribe( MishkaInstaller.get_config(:pubsub) || MishkaInstaller.PubSub, "setting" ) end @doc delegate_to: {MishkaDeveloperTools.DB.CRUD, :crud_add, 1} def create(attrs) do crud_add(attrs) |> notify_subscribers(:setting) end @doc delegate_to: {MishkaDeveloperTools.DB.CRUD, :crud_add, 1} def create(attrs, allowed_fields) do crud_add(attrs, allowed_fields) |> notify_subscribers(:setting) end @doc delegate_to: {MishkaDeveloperTools.DB.CRUD, :crud_edit, 1} def edit(attrs) do crud_edit(attrs) |> notify_subscribers(:setting) end @doc delegate_to: {MishkaDeveloperTools.DB.CRUD, :crud_edit, 1} def edit(attrs, allowed_fields) do crud_edit(attrs, allowed_fields) |> notify_subscribers(:setting) end @doc delegate_to: {MishkaDeveloperTools.DB.CRUD, :crud_delete, 1} def delete(id) do crud_delete(id) |> notify_subscribers(:setting) end @doc delegate_to: {MishkaDeveloperTools.DB.CRUD, :crud_get_record, 1} def show_by_id(id) do crud_get_record(id) end @doc delegate_to: {MishkaDeveloperTools.DB.CRUD, :crud_get_by_field, 2} def show_by_name(name) do crud_get_by_field("name", name) end @doc """ This is an aggregation function that includes editing or adding by name. """ def add_or_edit_by_name(data) do case show_by_name("#{data.name}") do {:ok, :get_record_by_field, :setting, repo_data} -> edit(data |> Map.merge(%{id: repo_data.id})) _ -> create(data) end end @doc """ Show all settings. """ @spec settings([ {:conditions, {String.t() | integer(), String.t() | integer()}} | {:filters, map()}, ... ]) :: any def settings(conditions: {page, page_size}, filters: filters) do try do query = from(set in SettingSchema) |> convert_filters_to_where(filters) from([set] in query, order_by: [desc: set.inserted_at, desc: set.id], select: %{ id: set.id, name: set.name, configs: set.configs, updated_at: set.updated_at, inserted_at: set.inserted_at } ) |> MishkaInstaller.repo().paginate(page: page, page_size: page_size) rescue _db_error -> case Code.ensure_compiled(module = Scrivener.Page) do {:module, _} -> struct(module, %{ entries: [], page_number: 1, page_size: page_size, total_entries: 0, total_pages: 1 }) {:error, _} -> %{entries: [], page_number: 1, page_size: page_size, total_entries: 0, total_pages: 1} end end end def settings(filters: filters) do try do query = from(set in SettingSchema) |> convert_filters_to_where(filters) from([set] in query, order_by: [desc: set.inserted_at, desc: set.id], select: %{ id: set.id, name: set.name, configs: set.configs, updated_at: set.updated_at, inserted_at: set.inserted_at } ) |> MishkaInstaller.repo().all() rescue _db_error -> [] end end def settings() do from(plg in SettingSchema) |> fields() |> MishkaInstaller.repo().all() end defp convert_filters_to_where(query, filters) do Enum.reduce(filters, query, fn {key, value}, query -> from(set in query, where: field(set, ^key) == ^value) end) end defp fields(query) do from([set] in query, order_by: [desc: set.inserted_at, desc: set.id], select: %{ name: set.name, configs: set.configs } ) end if Mix.env() == :test do defp notify_subscribers(params, _type_send), do: params else defp notify_subscribers({:ok, action, :setting, repo_data} = params, type_send) do Phoenix.PubSub.broadcast( MishkaInstaller.get_config(:pubsub) || MishkaInstaller.PubSub, "setting", {type_send, :ok, action, repo_data} ) params end defp notify_subscribers(params, _), do: params end @spec allowed_fields(:atom | :string) :: nil | list def allowed_fields(:atom), do: SettingSchema.__schema__(:fields) def allowed_fields(:string), do: SettingSchema.__schema__(:fields) |> Enum.map(&Atom.to_string/1) end