Posts de ‘Tiago Motta’

[Tiago Motta] TralhaController notificando obervadores por pattern

Saturday, August 1st, 2009

TralhaController é uma biblioteca javascript que permite que aplicações web que utilizam requisições assíncronas ofereçam URLs para cada contexto de navegação do usuário. Para saber mais sobre ela basta ler o artigo Mantendo contexto usando ajax que o Bruno Carvalho escreveu recentemente.

Porém uma coisa me incomodava no uso dessa classe. Para cada observador registrado eu precisava dentro do método update verificar se ele precisava agir de acordo com a URL. Isso acaba por tornar o código mais confuso pois obrigava-nos a misturar validações e lógica de negócio. Veja um exemplo abaixo:

var observadorBusca = { update:function(url) {  if( url.indexOf("#busca=")!=-1 ) {    //Executa a busca  }} };var observadorLink = { update:function(url) {  if( url.indexOf("#link=")!=-1 ) {    //Executa o link clicado  }} };TralhaController.addObserver(observadorBusca);TralhaController.addObserver(observadorLink);

Para tentar melhorar isso, pus a mão na massa e alterei o TralhaController permitindo registrar observadores que só fossem notificados diante de URLs que tivessem o padrão desejado. Utilizando então a última versão da biblioteca o código acima poderia então ser alterado para ficar da seguinte forma:

var observadorBusca = { update:function(url) { /* Executa a busca */ } };var observadorLink = { update:function(url) { /* Executa o link clicado */ } };

TralhaController.addObserver("\\#busca\=.*", observadorBusca);TralhaController.addObserver("\\#link\=.*", observadorLink);

Bem mais simples certo? É claro que há aqueles que não são muito fãs de expressões regulares e vão achar a primeira forma melhor. Para esses não há problema pois a forma antiga continua funcionando. Observadores registrados sem padrões continuam sendo notificados a toda e qualquer modificação de URL.

[Tiago Motta] Roda: Eu também já recriei

Friday, July 31st, 2009

Uma das discussões mais quentes do momento, e também uma das mais antigas, é sobre a mania que nós desenvolvedores temos de reinventar a roda. Eu mesmo já reinventei diversas vezes e hoje olho para trás e vejo quanto tempo poderia ter poupado ao usar alguma ferramenta já pronta, ou apenas ter adaptado uma que não se encaixava perfeitamente aos meus requisitos.

Há claro excessões, em que seu requisito é tão mínimo que reimplementar uma solução é mais rápido do que aprender uma já existente no mercado. Como foi o caso de um sistema que estávamos desenvolvendo em PHP e precisávamos de um framework apenas para separar a lógica da renderização de templates por tema. Validamos rapidamente diversos frameworks MVC e percebemos que era mais fácil criar em meia hora a seguinte classe:

class Renderizador {    function Renderizador($tema=null) {     $this->_dir = dirname(__FILE__) . "/templates/" . $this->tema;    }    public function put($nome,$obj) {     $this->$nome = $obj;    }    public function show($template) {     include(  $this->_dir . "/" . $template . ".php");    }}

A utilização dela era mais simples ainda. No exemplo abaixo as variáveis inseridas no renderizador ficam disponiveis para o template listagem.php através de $this, que nada mais é do que um arquivo php comum.

$renderizador = new Renderizador('cinza');$renderizador->put('lista',[1,2,3,4]);$renderizador->show('listagem');

Simples, sem precisar aprender nenhum framework ou linguagem de marcação nova. Em duas horas o time já estava trabalhando com a lógica separada da apresentação. Contudo essa é a exceção.

Em geral já recriei diversas rodas desnecessariamente desperdiçando muito tempo. Framework de mapeamento objeto relacional, CMS, blog e até mesmo o TimerTask do Java são alguns dos exemplos. Esse último me rendeu uma longa discussão com o Phillip Calçado na época em que ele trabalhava aqui. Felizmente ele foi persistente em me fazer desistir daquela implementação.

De qualquer forma, o importante é a lição aprendida. Hoje tento usar ao máximo ferramentas já disponíveis, e quando alguma não me atende perfeitamente, ao invés de começá-la do zero eu a altero e contribuo, como foi o caso de uma recente alteração que precisei fazer no fakeweb.

Outros membros da equipe também já vem de longe com esta mesma filosofia e estão constantemente contribuindo como Guilherme Cirne ao contribuir com o WillPaginate, o Anselmo também contribuindo com o Fakeweb e o Bruno Carvalho contribuindo com o TralhaController e o ExceptionNotifier.

O importante é aproveitar aquilo que a comunidade já lhe oferece pronto e testado. Economiza tempo seu, e do próximo desenvolvedor, que dará manutenção a algo que é padrão, com muita discussão em fóruns e muitas soluções documentadas.

[Tiago Motta] Dica rápida de charset para projetos rails com mysql

Saturday, July 18th, 2009

Se você está trabalhando em um projeto ruby on rails com banco mysql, e o charset definido tanto no servidor como no database.xml é UTF-8, tome o cuidado para que inserções no banco por conta de terceiros também seja feito neste charset.

Um simples insert feito na mão utilizando o cliente padrão do mysql pode te atrapalhar bastante. E o erro ficará bem difícil de encontrar pois este mesmo client exibirá o texto corretamente e só o rails entregará o dado incorreto, fazendo você acreditar que o problema está no ruby.

Para evitar isso, sempre que fizer inserts na mão e de massa de dados execute como primeira linha o seguinte comando:

charset utf8;

[Tiago Motta] Globo Vídeos: Quem viu este vídeo também assistiu

Thursday, July 9th, 2009

É com muito orgulho que anuncio que acaba de sair para degustação uma nova funcionalidade do Globo Vídeos. Foi uma alteração que durou apenas um dia de desenvolvimento envolvendo o time inteiro e que ficará no ar por um tempo ainda em versão de teste. Trata-se de uma forma de ofertar vídeos baseada nas preferências de nossos usuários. Chamamos a funcionalidade de “Quem viu este vídeo também assistiu”.

Como ainda está em versão “beta”, para visualizar a alteração é preciso ter o addon Grease Monkey instalado no seu Firefox, e instalar o script que habilita a funcionalidade beta. Depois basta acessar o Globo Vídeos para poder aproveitar a nova facilidade disponível. E se possível, nos dê feedback dizendo o que achou e se encontrou algum problema na utilização. A opinião de vocês é muito importante para que a gente possa melhorar.

[Tiago Motta] Teste de aceitação automático com múltiplas configurações no rails

Thursday, July 9th, 2009

Dado que uma aplicação possua duas maneiras ou mais de funcionar de acordo com alguns parâmetros de inicialização, como proceder com os testes de aceitação automáticos sem ter que iniciar e parar o servidor entre cada cenário ou grupo de cenários?

A solução simples, mas bem funcional que adotamos, foi ter uma task rake para inicializar vários servidores no ambiente local, cada um com um environment e uma porta diferente. Assim, ao testar uma determinada funcionalidade com determinada configuração basta acessar o servidor naquela porta.

A task rake que poderia até mesmo ser um shell script, ficou mais ou menos como mostrado abaixo. Créditos ao Tiago PacMan, mestre em shell, que fez a linha que finaliza os servidores.

desc 'Inicia servidores para teste de aceitação'task "server:test" do  system 'RAILS_ENV=test_conf_1 script/server -d -e test -p 3001'  sleep 1  system 'RAILS_ENV=test_conf_2 script/server -d -e test -p 3002'  sleep 1  system 'tail -f log/test.log'  system "ps aux | awk '/3001/{print $2}' | xargs kill -9"  sleep 1  system "ps aux | awk '/3002/{print $2}' | xargs kill -9"  sleep 1end

Repare que para este caso fizemos uma modificação no environments.rb para unificar os logs de todas os ambientes de teste.

Já no ambiente de integração contínua, onde utilizamos apache com passenger, foi mais simples ainda, bastando definir para diferentes VirtualHosts RailsEnvs diferentes.

[Tiago Motta] Resolvendo o "missing uri map" no mod_jk

Thursday, July 9th, 2009

Esses dias instalei o Ubuntu 9 em meu desktop e desde então tenho preparado o ambiente de desenvolvimento de diversas aplicações legadas. Uma delas necessita do apache conectando no tomcat pelo mod_jk. Após fazer a instalação de ambos e ter configurado os pontos de montagem do módulo, tudo de acordo com minha instalação antiga, deparei-me no log com o seguinte erro:

jk_translate::mod_jk.c (3038): missing uri map for tiago.motta:/MeuPathAqui

Descobri em uma grande thread de IRC que o problema ocorre quando o apache possui algum VirtualHost configurado, e que para resolver isso basta habilitar a configuração “JkMountCopy On” no VirtualHost correspondente.

[Tiago Motta] DynamicStream garantindo compatibilidade com flash 9

Saturday, June 6th, 2009

Ao implementar o DynamicStream em seu flash, teoricamente pararia de funcionar em clientes com a versão 9, pois algumas das classes e métodos necessários para seu uso só estão disponíveis apartir da versão 10.

Para evitar isso a Adobe disponibilizou um artigo mostrando como integrar o DynamicStream em um player antigo, para que só utilize o recurso novo quando o plugin do cliente estiver na versão 10, garantindo assim a compatibilidade. Este artigo possui até mesmo um exemplo, que embora funcione sem problemas em flash 9, quando integrado em outros projetos não funciona.

O problema é um bug na classe de referência que a Adobe oferece em diversos de seus artigos sobre essa funcionalidade. O erro fica evidente quando utilizamos um flash player debugger de versão 9 sobre o swf gerado, até mesmo os de exemplo da empresa.

verifyError: Error #1053: Illegal override of play2 in DynamicStream.

Esse erro ocorre porque a classe DynamicStream de referência sobrepõe o método play2 de NetStream apenas para anulá-lo. Com isso o plugin fica obrigado a verificar a existência do método play2 em NetStream e acaba dando o erro, pois tal método só está disponível apartir da versão 10.

Removendo esse método da classe DynamicStream de referência, tudo passa a funcionar, pois o acesso aos recursos existentes nas versões maiores ficam restritos ao conteudo dos métodos, que só serão avaliados em tempo de execução.

Não fosse o Bruno FMS me dar a dica do flash player debugger, perderia mais um bom tempo testando diversos artíficios para tentar fazer o código rodar em flash 9.

[Tiago Motta] Iptable para testar fallback para rtmpt no flash

Tuesday, June 2nd, 2009

Para testar se o fallback do seu flash player está funcionando corretamente, e acessando o flash media server pela porta 80 com rtmpt, basta configurar seu iptables para rejeitar ou deletar os pacotes da porta 1935, que é a padrão do FMS:

sudo iptables -A OUTPUT -p tcp --dport 1935 -j REJECT

ou

sudo iptables -A OUTPUT -p tcp --dport 1935 -j DROP

Sem esquecer de ao finalizar seus testes limpar o iptables para continuar seus testes:

sudo iptables -F

[Tiago Motta] Padrões de URLs com expressões regulares no Fakeweb

Monday, May 11th, 2009

Ao usarmos o Fakeweb aqui onde trabalho encontramos a necessidade de registrar grupos de URLs de acordo com um padrão. Inspirado no Anselmo Alves, colega de minha equipe que corrigiu um bug nesta mesma gem, alterei-a de forma a permitir o registro de URLs utilizando regex.

Com essa alteração, se por exemplo você quiser que todas as chamadas a um determinado host sejam respondidas com uma determinada string, basta registrar como o mostrado abaixo:

FakeWeb.register_uri(:get, /programandosemcafeina\.blogspot\.com/, :string => "Meu blog")

O principal desafio no desenvolvimento dessa nova funcionalidade foi não quebrar compatibilidade com o uso anterior. Dessa forma, os registros de URLs absolutas passaram a ter uma prioridade maior independente da ordem em que forem registradas. Ou seja, os retornos de acordo com as expressões regulares só são executados se a URL absoluta solicitada não estiver registrada. Veja o exemplo abaixo:

FakeWeb.register_uri(:get, "http://programandosemcafeina.blogspot.com/search/label/rails", :string => "Label Rails")FakeWeb.register_uri(:get, /programandosemcafeina\.blogspot\.com/, :string => "Meu blog")FakeWeb.register_uri(:get, "http://programandosemcafeina.blogspot.com/search/label/ruby", :string => "Label Ruby")

Net::HTTP.get(URI.parse("http://programandosemcafeina.blogspot.com/search/label/rails"))=> "Label Rails"

Net::HTTP.get(URI.parse("http://programandosemcafeina.blogspot.com/search/label/ruby"))=> "Label Ruby"

Net::HTTP.get(URI.parse("http://programandosemcafeina.blogspot.com/search/label/rmagick"))=> "Meu blog"

Já solicitei ao Chris Kampmeier a integração do meu fork, mas enquanto ela não é feita, você pode utilizar a gem gerada diretamente do meu repositório no Github. Basta intalar da seguinte forma:

gem sources -a http://gems.github.comsudo gem install timotta-fakeweb

[Tiago Motta] Undefined method request_uri com HTTParty

Monday, May 4th, 2009

Dica rápida para quem está utilizando HTTParty: Se por um acaso você se deparar com o seguinde erro:

undefined method `request_uri' for #<URI::Generic:0xb03919c>/mnt/apps/filmes/vendor/gems/httparty-0.3.1/lib/httparty/request.rb:56:in `setup_raw_request'/mnt/apps/filmes/vendor/gems/httparty-0.3.1/lib/httparty/request.rb:39:in `perform'/mnt/apps/filmes/vendor/gems/httparty-0.3.1/lib/httparty.rb:153:in `perform_request'/mnt/apps/filmes/vendor/gems/httparty-0.3.1/lib/httparty.rb:119:in `get'/mnt/apps/filmes/app/models/Filme.rb:25:in 'com_tags'

Não se desespere, URI:Generic realmente não possui o método request_uri. O problema é na incialização do HTTParty. Se base_uri estiver nulo qualquer requisição utilizando a classe obterá esse erro. Teste você mesmo algo como:

class A  include HTTParty  base_uri nil  format :xmlend

A.get('/search/label/ruby')

Ao corrigir a inicialização de base_uri o erro deixa de acontecer:

class A  include HTTParty  base_uri 'http://programandosemcafeina.blogspot.com'  format :xmlend

A.get('/search/label/ruby')

O problema é passível de ocorrer principalmente se base_uri for configurável de acordo com o ambiente em que a aplicação estiver rodando.