README.md

# Sobre o Skeleton SoftDelete

O Skeleton SoftDelete ajuda no tratamento de dados excluídos em sua aplicação, onde, nada é realmente deletado.
O que o SoftDelete faz é sempre que houver um delete em uma tabela, ele irá marcar com uma flag `deleted_at` a linha para desmonstrar que foi excluída.
Toda técnica se baseia na criação de views, triggers e funções diretamente no banco de dados.

# Funcionamento

## Função para exclusão

A funcão `soft_delete()` é responsável por marcar a linha como excluída, ou seja, receberá um valor na coluna `deleted_at`.

## View filtrando registro ativos

A view receberá o nome da sua tabela + `_without_deleted`.
Ela será sua tabela de registros ativos, filtrando os registro deletados.
É essa view que você precisará utilizar no seu schema (elixir).

## Trigger que invocará a função de exclusão

Essa função será criada em sua view, onde, após um `DELETE` no banco, será invocada a funcão `soft_delte` e ao invés de excluir, será marcada como excluída.

## View VS tabela

É importante entender a diferença entre a view e sua tabela.
A view é nada mais é do que uma query em sua tabela, filtrnado por registro não removidos. Já
a tabela, funciona de maneira normal, retornando todos os dados, incluíndo os excluídos.

## Instalação

```elixir
def deps do
  [
    {:skeleton_soft_delete, "~> 1.0.0"}
  ]
end
```

## Configuração

```elixir
config :skeleton_soft_delete, view_suffix: "_without_deleted"
```

Essa é a configuração padrão, você não precisa declará-la se não desejar mudar o sufixo da view.

## Criando o contexto

```elixir
# lib/app/app.ex

defmodule App do
  def schema do
    quote do
      use Ecto.Schema
      import Skeleton.SoftDelete.Schema
      import Ecto.Changeset
    end
  end

  def migration do
    quote do
      use Ecto.Migration
      import Skeleton.SoftDelete.Migration
    end
  end

  defmacro __using__(which) when is_atom(which) do
    apply(__MODULE__, which, [])
  end
end
```

### Criando a migration

```elixir
# priv/migrations/00000000000000_create_users.exs

defmodule App.Repo.Migrations.CreateUsers do
  use App, :migration

  def change do
    before_setup_soft_delete(:users, :user)

    create table(:users, primary_key: false) do
      add :id, :binary_id, primary_key: true
      add :email, :string

      add_soft_delete_field()
<<<<<<< HEAD
=======

>>>>>>> Release 1.0.0
      timestamps()
    end

    create unique_index(:users, [:email])

    after_setup_soft_delete(:users, :user)
  end
end
```

A função `before_setup_soft_delete` será responsável por remover a view `_without_deleted` caso a mesma tenha sido criada anteriormente e tamém a trigger responsável por não deletar o registro e sim informar uma data de deleção `deleted_at`. Essa remoção se faz necessária pois caso seja incluído ou alterado um algum campo, as atualizações dos campos serão contemplados na nova view que será criada através da função `after_setup_soft_delete` que será detalhada a baixo.

A funcão `add_soft_delete_field()` irá criar a columna `deleted_at` em sua tabela. Essa coluna será responsável por informar que e quando aquele registro foi excluído.

<<<<<<< HEAD
Já a funcão `after_setup_soft_delete` irá criar o índice o índice, view e trigger.
=======
A função `after_setup_soft_delete` será responsável por recriar a view `_without_deleted` e também a trigger do soft_delete.
>>>>>>> Release 1.0.0

### Criando o Schema

```elixir
# lib/app/accounts/user/user.ex

defmodule App.Accounts.User do
  use App, :schema

  schema soft_delete("users") do
    field :email, :string

    soft_delete_field()
    timestamps()
  end

  def with_deleted do
    {"users", App.Accounts.User}
  end
end
```

A partir de agora, qualquer `Repo.delete` utilizando seu schema `User`, irá sinalizar que a linha foi excluída.
Você poderá realizar queries com segurança nesse schema `User`, pois ele sempre filtrará os registros excluídos.

<<<<<<< HEAD
Caso voê precise realmente trazer os registros excluídos em uma query, basta utilizar o Schema assim: `User.with_deleted()`.
=======
Caso você precise realmente trazer os registros excluídos em uma query, basta utilizar o Schema assim: `User.with_deleted()`, exemplo: `Repo.all(User.with_deleted())` trará todos os registros, incluindo os deletados. Já Repo.all(User) trará apenas os registros que não foram marcados como deletados, ou seja, os que o processo do soft_delete não incluiu uma data no campo `deleted_at`.
>>>>>>> Release 1.0.0