#! /usr/bin/env ruby
if ARGV.size == 0
puts "Usage: #{__FILE__} (files to format)"
end
File.open("out.txt", "w") do |out|
ARGV.each do |filename|
out.puts "<pre>"
out.puts File.read(filename).gsub("<","<")
out.puts "</pre>"
end
end
Mostrando postagens com marcador Ruby. Mostrar todas as postagens
Mostrando postagens com marcador Ruby. Mostrar todas as postagens
segunda-feira, dezembro 17, 2007
"Codifier"
No post sobre Dificuldades Técnicas, havia mencionado que criei um script para formatar trechos de código para postar aqui. Ei-lo:
Chamadas Periódicas Sem Atropelo
Recentemente, precisei criar uma página que fazia chamadas periódicas ao servidor, para saber se um determinado processamento longo havia acabado, e carregar os resultados no caso positivo. No Rails, a melhor maneira de se fazer isso é com a função
Tornar as chamadas síncronas resolvia este problema, mas fazia o browser congelar completamente nos n*X segundos que a resposta demorava para carregar. Então, a saída que eu acabei utilizando foi criar uma variável de "estado", manipulada pelos callbacks do Prototype, para garantir que apenas uma chamada assíncrona executasse por vez.
Este é o resultado:
A primeira variável ("stop_polling") tem seu valor mudado pelo servidor quando os resultados ficam prontos. A segunda é alterara pelo próprio script para impedir que uma nova chamada seja executada enquanto a anterior ainda está esperando sua resposta. Com isso, o browser do usuário não congela.
periodically_call_remote, que dispara uma chamada AJAX em intervalos regulares. Mas, aí, como é de praxe, encontrei um pequeno problema quando o código foi para o ambiente de integração. As chamadas são assíncronas (o primeiro A do AJAX), acontecendo a cada X segundos, mas a chamada que finalmente carregava os resultados demora mais de X segundos para ser completa. Então, no meio do carregamento, uma outra chamada era iniciada e terminava justo a tempo de substituir a maravilhosa tela de resultados pela tela de "por favor espere".Tornar as chamadas síncronas resolvia este problema, mas fazia o browser congelar completamente nos n*X segundos que a resposta demorava para carregar. Então, a saída que eu acabei utilizando foi criar uma variável de "estado", manipulada pelos callbacks do Prototype, para garantir que apenas uma chamada assíncrona executasse por vez.
Este é o resultado:
<script>
var stop_polling = false;
var polling = false;
</script>
<%= periodically_call_remote(
:url => ping_search_search_results_url(@search),
:method => :get,
:frequency => 3,
:condition => "stop_polling == false && polling == false",
:after => "polling = true",
:complete => "polling = false"
) %>
A primeira variável ("stop_polling") tem seu valor mudado pelo servidor quando os resultados ficam prontos. A segunda é alterara pelo próprio script para impedir que uma nova chamada seja executada enquanto a anterior ainda está esperando sua resposta. Com isso, o browser do usuário não congela.
terça-feira, novembro 20, 2007
Alterando Plugins de Rails - O Método do "Gêmeo Maligno"
Uma das coisas boas do Rails é o sistema de plugins, que permite aumentar a funcionalidade do framework de várias maneiras. Mas existe um problema bem comum associado a ele: muitas vezes um determinado plugin quase faz aquilo que você quer, então você precisa alterá-lo para que ele se adapte melhor. Como fazer isso?
Este artigo do Err the blog mostra um método bastante interessante.
Este artigo do Err the blog mostra um método bastante interessante.
segunda-feira, outubro 22, 2007
Muito cuidado...
... se você começou a programar Ruby vindo do Java. Em Java, new Date() cria um objeto com o valor da data de hoje. Em Ruby, Date.new cria uma data com o valor mínimo (o primeiro dia do calendário Juliano) - para fazer o mesmo use Date.today .
quarta-feira, setembro 19, 2007
Behavior Driven Development
Muita gente fala como testes unitários são importantes, e alguns até dizem que eles deveriam ser escritos antes do código, prática que hoje possui sua própria buzzword: Test Driven Development, ou TDD.
Concordo 100%, mas nunca fui muito bom nisso. Não conseguia pensar com clareza nos testes, e portanto não conseguia escrever testes que valessem a pena rodar. A situação só mudou no projeto onde estou trabalhando agora, que usa uma prática que evoluiu a partir do TDD. A buzzword aqui é Behavior Driven Development, ou BDD.
Basicamente, BDD é uma maneira de escrever testes unitários mais compatível com o processo de pensamento da maioria de nós, reles mortais. Pouca gente consegue pensar nas coisas em termos de testes unitários, mas quase qualquer um consegue descrever como um determinado sistema deveria se comportar. Uma ferramenta de BDD deve permitir ao programador escrever testes de uma forma que se aproxima das frases usadas para descrever o comportamento do sistema.
Concordo 100%, mas nunca fui muito bom nisso. Não conseguia pensar com clareza nos testes, e portanto não conseguia escrever testes que valessem a pena rodar. A situação só mudou no projeto onde estou trabalhando agora, que usa uma prática que evoluiu a partir do TDD. A buzzword aqui é Behavior Driven Development, ou BDD.
Basicamente, BDD é uma maneira de escrever testes unitários mais compatível com o processo de pensamento da maioria de nós, reles mortais. Pouca gente consegue pensar nas coisas em termos de testes unitários, mas quase qualquer um consegue descrever como um determinado sistema deveria se comportar. Uma ferramenta de BDD deve permitir ao programador escrever testes de uma forma que se aproxima das frases usadas para descrever o comportamento do sistema.
Uma boa introdução ao BDD, usando Java e a ferramenta JBehave, pode ser encontrado aqui. Para os sortudos (que não precisam usar Java para isso), existe o RSpec, para Ruby. Compare as sintaxes dos dois, apresentadas no link. Se eu fosse obrigado a iniciar um projeto em Java, eu provavelmente escolheria o RSpec rodando em JRuby como ferramenta de testes.
segunda-feira, setembro 17, 2007
Padrões de Projeto em Linguagens dinâmicas
Padrões de Projeto (os famosos Design Patterns) parecem ser uma coisa pela qual todo desenvolvedor se apaixona em algum ponto da carreira. No meu antigo emprego eles eram praticamente idolatrados. A idéia básica é ótima: reunir problemas comuns e dar nome a eles, para facilitar a conversa. O problema é que o livro original também fornecia receitas, e é por elas que as pessoas tendem a se apaixonar, mesmo quando um dos autores já disse que elas eram "paliativos para C++".
Eis um artigo do Neal Ford explicando porque essas receitas não têm tanto valor assim quando se trata de aplicar os padrões a linguagens de programação diferentes (especialmente linguagens dinâmicas).
Eis um artigo do Neal Ford explicando porque essas receitas não têm tanto valor assim quando se trata de aplicar os padrões a linguagens de programação diferentes (especialmente linguagens dinâmicas).
sábado, agosto 18, 2007
Vlad, o Instalador
Com certeza um dos programas de nome mais criativo que eu já vi até agora. Vlad the Deployer é o nome de um sistema de deployment de aplicativos web escrito em Ruby, feito para concorrer com o Capistrano, outro sistema com a mesma finalidade.
terça-feira, julho 17, 2007
Introdução ao JRuby
Na IBM DeveloperWorks. Perfeito para quem está curioso sobre Ruby ou JRuby mas não sabe por onde começar ( o que significa que talvez eu leia o artigo com mais atenção no futuro),
quarta-feira, julho 11, 2007
Buildr
Eu gosto da idéia por trás do Ant - um sistema para automatizar aquelas tarefas repetitivas que fazem parte to desenvolvimento de qualquer software razoavelmente complexo. O que eu não gosto é ter que mexer em um arquivo XML enorme e ficar digitando tags e atributos a torto e a direito para programar a menor das tarefas nele.
O problema é que, quando o projeto é em Java, não existe nenhuma outra ferramenta do gênero que seja mais integrada à linguagem do que o Ant. Para usar algo mais amigável, você teria que programar sua própria integração entre essa nova ferramenta e a JVM.
Felizmente, alguém já fez isso: o Buildr é uma ferramenta de automação de build específica para projetos Java, mas toda feita em Ruby. Ele usa o Rake como base, e foi feito para substituir o Maven 2.0 (baseado em Ant...) sem que seja necessário nenhuma grande alteração no ambiente de desenvolvimento. Ele possui integração com o ant, de modo que não seria sequer necessário refazer as tasks antigas.
Com ele, é possível criar tasks usando Ruby, o que é muito melhor que tentar se virar com o limitado XML declarativo do Ant.
O problema é que, quando o projeto é em Java, não existe nenhuma outra ferramenta do gênero que seja mais integrada à linguagem do que o Ant. Para usar algo mais amigável, você teria que programar sua própria integração entre essa nova ferramenta e a JVM.
Felizmente, alguém já fez isso: o Buildr é uma ferramenta de automação de build específica para projetos Java, mas toda feita em Ruby. Ele usa o Rake como base, e foi feito para substituir o Maven 2.0 (baseado em Ant...) sem que seja necessário nenhuma grande alteração no ambiente de desenvolvimento. Ele possui integração com o ant, de modo que não seria sequer necessário refazer as tasks antigas.
Com ele, é possível criar tasks usando Ruby, o que é muito melhor que tentar se virar com o limitado XML declarativo do Ant.
terça-feira, junho 26, 2007
"Auto-complete" Avançado em Rails
Atenção! Nerdice avançada abaixo! Este post discute como implementar campos com "auto-complete" avançado em Rails. Se você não tem a mínima idéia do que seja um "auto-complete" básico, recomendo que leia este tutorial.
O Rails vêm com duas bibliotecas de Javascript para facilitar a implementação de interfaces AJAX em suas aplicações: a Prototype (para requisições assíncronas básicas) e a Script.aculo.us para "efeitos especiais".
Um dos efeitos especiais mais apreciados pelo usuário é o tal "auto-complete", onde ele começa a digitar algo em um campo de texto e vê, magicamente, um menu aparecer logo abaixo com várias alternativas que ele pode escolher com o mouse ou as setas do teclado, fazendo com que o valor do campo seja completado automaticamente com a opção escolhida. De acordo com o Agile Web Development with Rails, a reação inicial do usuário ao usar isso pela primeira vez é algo entre surpresa e admiração. O mesmo livro explica como usar os helpers do Rails para implementar o efeito.
Os helpers ajudam mesmo, mas como tudo no Rails eles cuidam apenas do caso mais comum. Fazer algo mais complexo vai tomar alguns minutos do seu tempo.
Por exemplo, ontem eu precisei de um "auto-complete" que preenchia vários campos da mesma página, ao invés de apenas um. Basicamente, o usuário escolhia o nome de um objeto, e os campos eram preenchidos com informações desse objeto. Eis como isso foi feito:
Um dos elementos de um auto-complete básico, como pode ser visto nos bons tutoriais on-line, é um partial contendo o template para o fragmento de HTML retornado pela chamada ao auto-complete (normalmente a lista de nomes). Ele se parece com algo do tipo:
A primeira coisa a fazer é alterar o fragmento acima para que retorne os demais atributos dos quais precisamos, mas que ainda assim só mostre o nome para o usuário.
Na sua folha de estilo, você coloca algo do tipo "span.hidden { display: none }" , fazendo com que os attributos marcados como hidden acima não apareçam.
E, para finalizar, inclua o método abaixo entre seus helpers customizados:
O método acima funciona de maneira parecida com o helper padrão, apesar de aceitar uma variedade menor de parâmetros. O que ele faz é gerar um bloco de Javascript que cuida das funções de auto-complete avançadas. Os parâmetros que ele deve receber são:
field_id - o identificador (valor do atributo "id") do campo "primário", ou seja, aquele em que o usuário digita as informações.
div_id - o identificador do "div" que vai mostrar as opções.
url - um hash do tipo que se passa ao método url_for, com a URL da qual serão recuperadas as opções.
fields - um array contendo os mesmos nomes dos campos colocados no partial acima, na mesma ordem.
Basta usar o helper acima na hora de implementar o "auto-complete" avançado:
<%= custom_auto_complete(...) %>
O Rails vêm com duas bibliotecas de Javascript para facilitar a implementação de interfaces AJAX em suas aplicações: a Prototype (para requisições assíncronas básicas) e a Script.aculo.us para "efeitos especiais".
Um dos efeitos especiais mais apreciados pelo usuário é o tal "auto-complete", onde ele começa a digitar algo em um campo de texto e vê, magicamente, um menu aparecer logo abaixo com várias alternativas que ele pode escolher com o mouse ou as setas do teclado, fazendo com que o valor do campo seja completado automaticamente com a opção escolhida. De acordo com o Agile Web Development with Rails, a reação inicial do usuário ao usar isso pela primeira vez é algo entre surpresa e admiração. O mesmo livro explica como usar os helpers do Rails para implementar o efeito.
Os helpers ajudam mesmo, mas como tudo no Rails eles cuidam apenas do caso mais comum. Fazer algo mais complexo vai tomar alguns minutos do seu tempo.
Por exemplo, ontem eu precisei de um "auto-complete" que preenchia vários campos da mesma página, ao invés de apenas um. Basicamente, o usuário escolhia o nome de um objeto, e os campos eram preenchidos com informações desse objeto. Eis como isso foi feito:
Um dos elementos de um auto-complete básico, como pode ser visto nos bons tutoriais on-line, é um partial contendo o template para o fragmento de HTML retornado pela chamada ao auto-complete (normalmente a lista de nomes). Ele se parece com algo do tipo:
<ul>
<% @objects.each do |object| %>
<li><%= object.name %></li>
</ul>
A primeira coisa a fazer é alterar o fragmento acima para que retorne os demais atributos dos quais precisamos, mas que ainda assim só mostre o nome para o usuário.
<ul>
<% @objects.each do |object| %>
<li>
<span><%= object.name %></span>
<span class="hidden"><%= object.outro_atributo %></span>
<span class="hidden"><%= object.e_mais_outro %></span>
...
</li>
</ul>
Na sua folha de estilo, você coloca algo do tipo "span.hidden { display: none }" , fazendo com que os attributos marcados como hidden acima não apareçam.
E, para finalizar, inclua o método abaixo entre seus helpers customizados:
def custom_auto_complete( field_id, div_id, url, fields )
assignments = []
fields.each_with_index do |field, i|
assignments << "$('#{field}').value = dn[#{i}].firstChild.nodeValue;"
end
<<-END
<script type="text/javascript">
new Ajax.Autocompleter( '#{field_id}',
'#{div_id}',
'#{url_for( url )}',
{ updateElement: function( selected ) {
Element.cleanWhitespace( selected );
dn = selected.childNodes;
#{assignments.join("\n")}
}
} );
</script>
END
end
O método acima funciona de maneira parecida com o helper padrão, apesar de aceitar uma variedade menor de parâmetros. O que ele faz é gerar um bloco de Javascript que cuida das funções de auto-complete avançadas. Os parâmetros que ele deve receber são:
field_id - o identificador (valor do atributo "id") do campo "primário", ou seja, aquele em que o usuário digita as informações.
div_id - o identificador do "div" que vai mostrar as opções.
url - um hash do tipo que se passa ao método url_for, com a URL da qual serão recuperadas as opções.
fields - um array contendo os mesmos nomes dos campos colocados no partial acima, na mesma ordem.
Basta usar o helper acima na hora de implementar o "auto-complete" avançado:
<%= custom_auto_complete(...) %>
segunda-feira, junho 25, 2007
Coisas Importantes para se Saber ao Aprender Ruby on Rails
Uma lista bem interessante de coisas básicas que todo programador que quer trabalhar com Ruby on Rails deve saber.
Assinar:
Comentários (Atom)