From f446e398a57a7e5a37edf5621fd5995c3fc5b007 Mon Sep 17 00:00:00 2001 From: dunossauro Date: Fri, 4 Oct 2024 22:47:56 -0300 Subject: [PATCH] =?UTF-8?q?[REV]=20Revis=C3=A3o=20de=20grafia=20da=20cria?= =?UTF-8?q?=C3=A7=C3=A3o=20de=20eventos=20na=20aula=2004?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit related #251 --- aulas/04.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/aulas/04.md b/aulas/04.md index 6b240668..b05aa478 100644 --- a/aulas/04.md +++ b/aulas/04.md @@ -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. @@ -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 @@ -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 @@ -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) == { @@ -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. @@ -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" %}