27 de abril de 2011

Controle total sobre seus models

Toda aplicação web2py que usa banco de dados tem um diretório chamado models.

Esse diretório é particularmente importante devido a alguns fatores:
  1. Os arquivos do diretório models são executados em ordem alfabética;
  2. É ali que ficam as definições das tabelas dos bancos de dados de sua aplicação;
  3. Os objetos definidos por esses arquivos ficam disponíveis com escopo global na aplicação. Ou seja, podem ser acessados pelos controladores e pelas views.
Talvez a caracterísitica que mais exija atenção, é a primeira: execução em ordem alfabética.

Algumas pessoas iniciantes têm certa dificuldade com isso e acham meio estranho esse comportamento. Eu também achava, até concluir que esse é o jeito mais intuitivo para tudo funcionar.

Entretanto, para evitar alguns inconvenientes que esse funcionamento pode trazer, precisamos adotar uma nomenclatura clara e o mais simples possível para organizar nossos scripts dentro do diretório models.

Eu adoto a seguinte estrutura básica:
  1. models/0_db.py
  2. models/1_menu.py
  3. models/5_models.py
  4. models/5_validators.py
Em quê isso ajuda?

Eu renomeio o db.py gerado automaticamente pelo web2py para 0_db.py. Assim, garanto que todas as definições básicas são executadas antes de qualquer coisa. O objeto DAL, que fornece toda a funcionalidade de acesso a dados, é criado nesse script.

Também renomeio o menu.py para 1_menu.py fazendo com que as definições de menu sejam executadas depois da instanciação do objeto DAL.

Com esses nomes modificados, garanto que o esqueleto gerado automaticamente pelo web2py vai ser executado antes das partes que eu vou desenvolver depois.

A partir daí, escrevo o models/5_models.py com todas as definições de tabelas. Vale ressaltar que eu deixo dentro desse arquivo apenas os db.define_table().

Para escrever os validadores, eu crio o models/5_validators.py. Mas por que separado? Primeiro, porque o web2py recomenda que você não coloque os validadores dentro do db.define_table(). Segundo, porque nesse ponto eu tenho certeza de que todas as tabelas já foram definidas. Assim, garanto que qualquer referência cruzada entre elas funcione sem precisar alterar a ordem de criação delas. Às vezes isso desorganiza o script de criação das tabelas.

Se eu tiver muitas tabelas, nada me impede de dividir a definição delas em vários scripts, por módulos, por exemplo: 5_models_estoque.py, 5_models_financeiro.py, etc. E, da mesma forma, os validadores.

Aqui, sua criatividade é quem manda, mas lembre-se de alguns princípios:
Explícito é melhor do que implícito.
Simples é melhor do que complexo.
Linear é melhor do que encadeado.
A legibilidade conta.
Quando encontrar a ambiguidade, recuse a tentação de adivinhar.

20 de março de 2011

Sendo mais ágil com o appadmin

No artigo "Quem alterou um registro" eu mostrei como o web2py agiliza e padroniza a criação e controle de dados das tabelas automaticamente.

Mas quando estamos testando o aplicativo e usando o appadmin, precisamos de agilidade para incluir e alterar registros no bd.

Daí, para passar a validação de quem incluiu um registro, faça conforme abaixo:

""" Alterando o auth.signature para permitir
inserts anônimos pelo appadmin. """

db.minha_tabela.created_by.required = False
db.minha_tabela.created_by.requires = IS_EMPTY_OR( \
    db.carro.created_by.requires)

db.minha_tabela.modified_by.required = False
db.minha_tabela.modified_by.requires = IS_EMPTY_OR( \
    db.carro.modified_by.requires)

Assim, você não vai precisar escolher um autor para o registro.

Observações:
  1. Coloque o trecho de código mostrado, abaixo do db.define_table() da tabela que você está testando.
  2. Só use esse recurso em ambiente de desenvolvimento porquê você terá registros sem a identificação de quem os incluiu/alterou.

Fica a dica.

8 de fevereiro de 2011

Quem alterou um registro

Detalhes fazem a diferença, certo? O web2py se preocupa com eles para dar produtividade ao desenvolvedor.

Uma boa ideia é o auth.signature

Vamos a um exemplo:
db.define_table('cadastro',
  Field('nome', 'string', length=100),
  Field('telefone', 'string', length=20),
  auth.signature)

Esse comando vai criar uma tabela chamada cadastro com os campos id (criado automaticamente), nome e telefone, além de: created_on, created_by, modified_on e modified_by.

Isso faz com que possamos saber quando um registro foi incluído (created_on) ou alterado (modified_on).

O auth.signature funciona automaticamente integrado ao sistema de autenticação do web2py. Portanto, se um usuário logado incluir ou alterar o registro, o código de usuário dele ficará registrado nos campos created_by e modified_by.

Fica aí a dica.