Skip to content

Commit

Permalink
[REV] Revisão de grafia da criação de eventos na aula 04
Browse files Browse the repository at this point in the history
related #251
  • Loading branch information
dunossauro committed Oct 5, 2024
1 parent 6e18d94 commit f446e39
Showing 1 changed file with 12 additions and 12 deletions.
24 changes: 12 additions & 12 deletions aulas/04.md
Original file line number Diff line number Diff line change
Expand Up @@ -329,13 +329,11 @@ Neste caso, podemos ver que todos os nossos testes passaram com sucesso. Isso si

Embora tudo esteja se encaixando bem, esse teste não é muito legal, pois não faz a validação do objeto como um todo. Conseguimos garantir que toda a estrutura do bando de dados funciona, porém, não conseguimos garantir ainda que todos os valores estão corretos.

## [REV] Eventos do ORM
## Eventos do ORM

> TODO: Revisar toda a grafia desse tópico!
Embora nossos testes tenham sido executados corretamente, temos um problema se quisermos validar o objeto como um todo, por existirem alguns campos da tabela que fogem do mecanismo da criação do objeto `#!python (init=False)`.

Embora nossos testes tenham sido executados de forma correta, temos um problema se quisermos validar o objeto como um todo, pois existem algumas coisas que fogem do mecanismo da criação do objeto.

Um desses casos é o campo `created_at`. Quando configuramos o modelo, deixamos que o banco de dados defina seu horário e data atual para preencher esse campo. Será que existe uma forma de alterar esse comportamento durante os testes? Pra que possamos validar quando o objeto foi criado? A resposta é sim.
Um desses casos é o campo `created_at`. Quando configuramos o modelo, deixamos que o banco de dados defina seu horário e data atual para preencher esse campo. Será que existe uma forma de alterar esse comportamento durante os testes? Pra podermos validar quando o objeto foi criado? A resposta é sim.

O SQLAlchemy tem um sistema de eventos. Eventos são blocos de código que podem ser inseridos ou removidos antes e depois de uma operação.

Expand Down Expand Up @@ -379,13 +377,13 @@ event.listen(User, 'before_insert', hook) #(2)!
1. Qualquer função que for usada como um hook do evento de `before_insert` tem que receber os parâmetros `mapper`, `connextion` e `target`, mesmo que não os use.
2. Nesse exemplo o evento "ouvirá" [*listen*] o modelo `User` e toda vez que o ORM for inserir um registro desse modelo no banco (`before_insert`) ele executará a função `hook`.

A ideia por trás dos eventos é simplesmente passar algum modelo ou a sessão para que o ORM observe todas as vezes em que uma determinada operação foi executada e se ela tem algum hook sendo "ouvido" para aquela operação. Falando de forma clara, todas as vezes que `User` for inserido na base, antes disso a função `hook` será executada.
A ideia por trás dos eventos é simplesmente passar algum modelo ou a sessão para que o ORM observe todas às vezes em que uma determinada operação foi executada e se ela tem algum hook sendo "ouvido" para aquela operação. Falando de forma clara, todas às vezes que `User` for inserido na base, antes disso a função `hook` será executada.

> Você pode buscar por outros eventos de mapeamento na [Documentação do SQLAlchemy](https://docs.sqlalchemy.org/en/20/orm/events.html#mapper-events){:target="_blank"}
### Evento para manipular o tempo

Para fazer a validação de todos os campos do objeto durante os testes, podemos criar um evento que será executado durante o teste que faça que com os registros inseridos nesse teste tenham o horáiro manipulado, facilitando a comparação com um `created_at` fixo:
Para fazer a validação de todos os campos do objeto durante os testes, podemos criar um evento que será executado durante o teste que faça que com os registros inseridos nesse teste tenham o horário manipulado, facilitando a comparação com um `created_at` fixo:

```python title="tests/conftest.py" hl_lines="9 16 20"
from contextlib import contextmanager
Expand Down Expand Up @@ -417,7 +415,7 @@ def _mock_db_time(*, model, time=datetime(2024, 1, 1)): #(2)!
5. Retorna o datetime na abertura do gerenciamento de contexto.
6. Após o final do gerenciamento de contexto o hook dos eventos é removido.

A ideia por trás dessa função é ser um gerenciador de contexto (para ser chamado em um bloco `#!python with`). Toda vezes que um registro de `model` for inserido no banco de dados, se ele tiver o campo `created_at`, por padrão o campo será cadastrado na data '01/01/2024'. Facilitando a manutenção dos testes para validar a criação do objeto com a sua data.
A ideia por trás dessa função é ser um gerenciador de contexto (para ser chamado em um bloco `#!python with`). Toda vezes que um registro de `model` for inserido no banco de dados, se ele tiver o campo `created_at`, por padrão, o campo será cadastrado com a sua data pré-fixada '01/01/2024'. Facilitando a manutenção dos testes que precisam da comparação de data, pois será determinística.

#### Transformando o evento em uma fixture

Expand Down Expand Up @@ -470,7 +468,9 @@ O teste permanece praticamente igual, com a diferença de que todas as operaçõ

Isso faz com que durante o `commit`, quando os objetos são persistidos da sessão para o banco de dados, o evento de `before_insert` seja executado para cada objeto do modelo passado em `mock_db_time(model=*MODEL*)`.

Por conta do campo `created_at` agora ser determinístico podemos fazer uma comparação completa dos campos. Para simplificar a comparação, como nossos objetos de modelo são dataclasses, a função `dataclass.asdict`, converte uma dataclass para um dicionário:
Por conta do campo `created_at` agora ser determinístico podemos fazer uma comparação completa dos campos.

Para simplificar a comparação de todos os campos, como nossos objetos de modelo são dataclasses, a função `dataclass.asdict()`, converte uma dataclass para um dicionário:

```python title="Estudando a comparação"
assert asdict(user) == {
Expand All @@ -482,7 +482,7 @@ Por conta do campo `created_at` agora ser determinístico podemos fazer uma comp
}
```

Como o tempo agora é determinístico e contido no nosso gerenciador de contexto, podemos fazer a comparação determinística de todos os campos. Inclusive do `created_at`.
Como o tempo agora é determinístico e contido no nosso gerenciador de contexto, podemos fazer a comparação exata entre todos os campos. Inclusive `created_at`.

Desta forma, nossos modelos e testes de banco de dados agora em ordem, estamos prontos para avançar para a próxima fase de configuração de nosso banco de dados e gerenciamento de migrações.

Expand Down Expand Up @@ -854,8 +854,8 @@ E pronto! As mudanças que fizemos foram salvas no histórico do Git e agora est
mapped_column(onupdate=func.now())
```
2. Altere o evento de testes (`mock_db_time`) para ser contemplado no mock o campo `updated_at` na validação do teste.
2. Criar uma nova migração autogerada com alembic
3. Aplicar essa migração ao banco de dados
3. Criar uma nova migração autogerada com alembic
4. Aplicar essa migração ao banco de dados

{% include "templates/exercicios.md" %}

Expand Down

0 comments on commit f446e39

Please sign in to comment.