Elixir - Como fazer determinadas operações com a biblioteca Ecto (Parte 2)
Published: 2023-01-27 13:54:33

Vamos para segunda parte do nosso artigo, agora vamos as operações propriamente ditas.
## Fazendo Operações no banco de dados
Todas as operações que iremos fazer será usando o shell que o elixir nos oferece, então digite no terminal:

```
iex -S mix
```
## Operações sem usar Ecto.Schema
Algumas vezes será necessário fazer operações de banco de dados sem a utilização do Ecto.Schema, e apenas usar as tabelas associadas, porém mesmo sem a utilização do Ecto.Schema não vamos necessitar criar o SQL bruto.
### Busca
A primeira operação que vamos fazer será a de busca, com o seguinte comando podemos criar uma query para verificar todos os clientes inseridos no nosso banco de dados:

```
import Ecto.Query
alias PizzariaEcto.Repo
query = from("clients", select: [:name, :phone])
Repo.all(query)
```
O código acima vai criar o seguinte sql e executa-lo:

```
SELECT name, phone FROM clients
```
Como eu falei a um tempo quando criamos a query ela não será executada, pois o Ecto usa o padrão repositório, ou seja, apenas funções do repositório poderá operar em cima do banco de dados. Assim, essa função Repo.all() irá receber uma query(Uma struct Ecto.Query) e retornar uma lista de mapas contendo as informações no banco, mas como não temos nada no banco será retornado uma lista vazia, então vamos inserir algo no banco de dados.
### Inserção

```
data = [
	%{name: "Bruno Santos", phone: "999878767"},
  %{name: "Maria Pereira", phone: "994657876"},
  %{name: "Fábio Bio", phone: "999870900"}
]
Repo.insert_all("clients", data)
#=> {3, nil}
```
Com esse código inserirmos 3 clientes na nossa base de dados, então podemos novamente executar o comando de busca para ver esses clientes.
### Busca específica
Afim de poder executar uma operação de busca específica podemos executar:

```
import Ecto.Query
alias PizzariaEcto.Repo
query = from(c in "clients", where: c.name == "Bruno Santos", select: [:name, :phone])
Repo.all(query)
```
### Remoção
Afim de poder executar uma operação de remoção de dados podemos executar:

```
import Ecto.Query
alias PizzariaEcto.Repo
from(c in "clients", where: c.name == "Bruno Santos") |> Repo.delete_all
```
### Atualização
Podemos fazer atualizações também ainda sem usar schemas:

```
import Ecto.Query
alias PizzariaEcto.Repo
from(c in "clients", where: c.name == "Fábio Bio") |> Repo.update_all
```
## Operações usando o Ecto.Schema
Com os schemas em mãos podemos fazer a mesma coisa que fazermos sem os schemas, porém o retorno dessas operações vão está em estruturas elixir.
### Busca
As buscas usando Ecto.Schema é a mesma coisa de sem usa essa estrutura, mas o retorno da função será uma lista de estruturas elixir populadas.

```
import Ecto.Query
alias PizzariaEcto.{Repo, Client}
query = from(Client)
Repo.all(query)
#=> [%PizzariaEcto.Client{...},...]
```
### Buscas específicas
Podemos fazer retornos em estruturas elixir usando a função Repo.get_by().

```
import Ecto.Query
alias PizzariaEcto.{Repo, Client}

Repo.get_by(Client, name: "Maria Pereira")
#=> %PizzariaEcto.Client{...}
```
## Ecto.Changeset
Antes de fazermos operações com inserção e atualização de dados usando as estruturas elixir, podemos falar sobre a estrutura Ecto.Changeset. Esta estrutura nos permite criar casts e validações para dados que são inseridos pelo usuário. 

```
alias PizzariaEcto.Client
import Ecto.Changeset
params = %{name: "Mariana Bom", phone: "999808909", email: "mariana@gmail.com"}
changeset = cast(Client, params, [:name, :phone])
Repo.insert(changeset)
```
A função cast permiti filtrar quais chaves vão poder serem usadas para criação da estrutura PizzariaEcto.Client, e assim usando a função insert inserir no banco de dados. O ecto tem funções de validação como o validate_length que recebe um changeset e retorna um novo changeset com essa validação aplicada, então podemos melhorar o nosso código:

```
alias PizzariaEcto.Client
import Ecto.Changeset
params = %{name: "Mariana Bom", phone: "999808909", email: "mariana@gmail.com"}
changeset = cast(%Client{}, params, [:name, :phone]) |> validate_length(:phone, min: 9)
Repo.insert(changeset)
```
O código acima permite inserir apenas os dados de **name** e **phone** que tenha no mínimo 9 dígitos, caso alguma validação não ocorra a inserção não funcionará. 

Podemos fazer atualizações usando **changeset**, o seguinte código vai procurar um cliente chamado “Maria Bom”, criar um **changeset** com base nesse retorno e mandar para a função **update** para atualizar o banco.

```
alias PizzariaEcto.{Repo,Client}
import Ecto.Changeset
client = Repo.get_by(Client, name: "Mariana Bom")
changeset = change(client, name: "Mariana Ruim")
Repo.update(changeset)
#=> {:ok, struct_com_cliente_atualizado}
```
## Conclusão
No presente artigo vimos como a ferramenta Ecto nos possibilita fazer operações no banco de dados de nossa preferência. O uso do Ecto também se dá principalmente junto ao framework Phoenix que nos permite criar aplicações web poderosas, afim de resolver alguns problemas existentes.

## Referências
[Ecto Site Oficial](https://hexdocs.pm/ecto/Ecto.html)

[Programming Ecto - Build Database Apps in Elixir for Scalability and Performance](https://pragprog.com/titles/wmecto/programming-ecto/)