Para o conteúdo original acesse http://daniel.ruoso.com
Transações e Autorizações do jeito simples
18 de Agosto de 2009, 0:00 - sem comentários aindaEu realmente gosto de seguir o DRY: Don't Repeat Yourself. No desenvolvimento do Epitáfio (um sistema de gestão de cemitérios que eu mencionei outro dia), eu estava trabalhando nas minhas classes model - note que isso não é um model DBIC, mas uma classe normal que vai acessar um schema DBIC - e eu percebi que para cada um dos métodos eu precisaria de duas coisas:
- Embutir em uma transação, mais ou menos como:
$schema->txn_do(sub { ... })
- Autorizar em relação a uma role específica:
die 'Access denied!' unless $user->in_role('foo')
Então eu comecei a pensar no #catalyst se teria um jeito bonito de fazer isso. Eu já estava usando o Catalyst::Component::InstancePerContext, ams o mst rapidamente me guiou em evitar salvar o contexto no model, mas simplesmente pegar os valores que eu preciso de lá. Já que os meus models vão ter basicamente esse mesmo princípio, eu fiz uma superclasse:
package Epitafio::Model; use Moose; with 'Catalyst::Component::InstancePerContext'; has 'user' => (is => 'rw'); has 'dbic' => (is => 'rw'); sub build_per_context_instance { my ($self, $c) = @_; $self->new(user => $c->user->obj, dbic => $c->model('DB')->schema->restrict_with_object($c->user->obj)); } 1;
Veja que eu ainda estou usando o C::M::DBIC::Schema como sempre, mas eu estou, adicionalmente, fazendo um dbic schema local que é restrito de acordo com o usuário autenticado. Veja a documentação do DBIx::Class::Schema::RestrictWithObject para os detalhes, e mst++ pela dica.
Ok, agira as minhas classes model sabem quem é o usuário logado (independente do Catalyst) e também têm acesso ao dbic schema principal da aplicação. Agora precisamos apenas DRO - Don't Repeat Ourselves.
Seguindo, novamente, a dica do mst++, eu decidi não tentar uma solução fancy, e ir para o puro e simples:
txn_method 'foo' => authorize 'rolename' => sub { ... }
Para aqueles que não entenderam como isso é interpretado, poderia ser reescrito como:
txn_method('foo',authorize('rolename',sub { }))
Isso funciona da seguinte forma:
- authorize recebe o nome de uma role e a referência para o código, retornando outra referencia para um código que checa se o usuário tem a role antes de chamar o código efetivo.
- txn_method recebe o nome de um método e uma referência para um código e instala um coderef que embute o coderef passado em uma transação no namespace do pacote, como se fosse uma rotina regular.
Isso significa que você pode ter um txn_method sem authorize, mas iria requerer
our &foo = authorize 'rolename' => sub { ... }
para ter autorização sem transação. Mas como a minha aplicação eu vou precisar dos dois a maior parte do tempo, isso deve servir.
Mas para que o txn_method..authorize seja interpretado, as duas subs precisam estar no namespace do pacote em tempo de BEGIN, para resolver isso sem ter que colar as rotinas toda vida, escrevi um módulo simples Epitafio::ModelUtil que exporta-os.
package Epitafio::ModelUtil; use strict; use warnings; use base 'Exporter'; our @EXPORT = qw(txn_method authorized); sub txn_method { my ($name, $code) = @_; my $method_name = caller().'::'.$name; no strict 'refs'; *{$method_name} = sub { $_[0]->dbic->txn_do($code, @_) }; } sub authorized { my ($role, $code) = @_; return sub { if ($_[0]->user->in_role($role)) { $code->(@_); } else { die 'Access Denied!'; } } } 1;E agora o código do model é bonito e não repetitivo ;). Veja os fontes para a versão completa.
SMOPP5 first steps
12 de Agosto de 2009, 0:00 - sem comentários aindaDepois de um longo tempo imaginando quando esse dia chegaria, hoje o Paweł Murias criou um fork no github do interpretador perl para que possamos começar a trabalhar na integração do SMOP com o perl5.
Alguns de vocês já devem ter me ouvido falar que a principal razão para o SMOP existir hoje é a possibilidade de integração com o interpretador do perl5, de forma que possamos usar o Perl 6 com todas as bibliotecas da CPAN, incluindo as que dependem de XS, como o fantástico Gtk2-Perl.
De fato, eu venho bloqueando o pmurias em algumas coisas como trocar o referencecounting por um trace gc no SMOP exatamente porque isso iria fazer o SMOP incompatível com o perl5, e eu realmente quero que eles cooperem.
Esta integração deve ocorrer no nivel mais profundos dos perlguts, onde o interpretador do perl5 vai fazer o papel do interpretador do SMOP e todo SV* será também um SMOP__Object*.
Paweł adicionou o smop/base.h para o repositório do p5 e eu comecei adicionando o membro SMOP__ResponderInterface* para alguns valores do p5 (por enquanto o _SV_HEAD, que define os primeiros membros de todos os valores SV< e o PerlInterpreter). Isto é o primeiro passo que irá permitir que o SMOP use objetos do perl5 sem a necessidade de valores-proxy.
Depois de falar com o nothingmuch no #p5p, decidi anotar aqui o primeiro conjunto de objetivos para a integração SMOPP5:
- Fazer todo valor do perl um SMOP__Object*
- Implementar Responder Interfaces para cada um desses valores
- Implementar o SMOP interpreter and continuation class APIs no interpretador do perl5 (usando Coro::State por hora)
- Ter objetos SMOP visíveis no perl5 através de objetos-proxy, como acontece hoje
Este conjunto nos dá a integração SMOP->P5, depois disso precisaremos da integração P5->SMOP, que deverá envolver mexer em todas as macros do core do p5, o que é *muita* coisa, então não vou nem incluir nos nossos objetivos para fins de sanidade!
Far More Than You Ever Wanted To Know About Typeglobs, Closures and Namespaces
11 de Agosto de 2009, 0:00 - sem comentários aindaEstes são os sldies de uma apresentação que eu fiz em Lisboa, em um dos encontros técnicos realizados na época que eu morava lá.
Far More Than You Ever Wanted To Know About Typeglobs, Closures and Namespaces
Too much Perl 6
31 de Julho de 2009, 0:00 - sem comentários aindaEntão, ontem eu estava dando uma oficina de Perl usando Catalyst. A idéia era escrever um blog em 3 horas. Em um determinado ponto, eu escrevi o seguinte código:
sort { (stat $_)[10] } glob 'posts/*';
E não funcionou, porque o Perl 5 não DWIM quando eu tenho uma rotina de sort que recebe apenas um parâmetro, enquanto o Perl 6 iria perceber isso e usar o retorno da rotina como valor de ordenação depois. Basicamente, o Perl 6 implementa a Schwartzian Transform no seu core.
Epitáfio
30 de Julho de 2009, 0:00 - Um comentárioOs monges Perl do Brasil aceitaram um desafio com uma característica social muito relevante. Estamos trabalhando no nosso tempo livre para desenvolver um sistema para gestão de cemitérios públicos. Pouca gente sabe, mas os cemitérios públicos exercem um papel fundamental no respeito aos direitos humanos, bem como em relação à saúde pública, dando à população que não tem recursos para pagar um jazigo em um cemitério particular tenha um velório e um enterro dignos.
Nesse momento já estabelecemos as funcionalidades para a primeira versão, e a expectativa de prazo, que é ter o sistema já rodando no cemitério para o dia de finados. Ontem terminamos a primeira proposta para o modelo de dados:
As discussões sobre o sistema acontecem no canal #brasil-pm do irc.perl.org, temos um espaço no wiki do perl.org.br para documentar o processo de desenvolvimento e um espaço no github para hospedar os códigos fonte.
O sistema vai ter uma interface Web e vai usar o PostgreSQL, especialmente por conta das funcionalidades para tratamento de timestamp e pela possibilidade de depois usar esses dados como objetos do PostGIS, permitindo que os jazigos sejam geo-referenciados dentro do mapa do cemitério.
A medida em que avançarmos nesse desenvolvimento vou postar as notícias aqui.