Ruby versus PHP: minha comparação subjetiva e desleal (Parte 1)
Meu trabalho atual envolve muita exportação de dados entre diferentes bancos de dados relacionais. Hoje me deparei com a seguinte situação: precisava extrair dados de uma base MySQL, formatá-los apropriadamente em um arquivo de texto, e então inseri-los no Moodle através de sua interface administrativa (que aceita arquivos tabulares como forma de cadastrar usuários “em lote”).
Minha tabela de origem possuía um campo fullname, mas o Moodle só
aceita firstname e lastname. Portanto, ou o meu SELECT quebraria
esses campos ou então eu utilizaria alguma linguagem para pré-processar
esses arquivos.
E foi aí que Ruby deu conta do recado muito bem. Essa dica vale para qualquer operação rápida de manipulação de arquivos que você não saiba fazer dentro do MySQL ou do Vim.
Minha consulta SQL gerava a seguinte saída (colunas nome de usuário, senha, nome completo e email):
fulano,123456,Fulano da Silva,fulano@teste.com
beltrano,123456,Beltrano da Silva,beltrano@teste.com
Mas o que eu queria era (note a vírgula entre o primeiro nome e o sobrenome):
fulano,123456,Fulano,da Silva,fulano@teste.com
beltrano,123456,Beltrano,da Silva,beltrano@teste.com
Ah, claro, se eu tivesse apenas duas linhas no arquivo eu não teria escrito o programa. Na verdade eram mais de 100. Então decidi escrever o seguinte programa Ruby para me ajudar.
#!/usr/bin/env ruby
File.open(ARGV[0]) do |f|
f.each_line do |line|
username, password, full_name, email = line.split(',')
first_name, last_name = full_name.split(' ', 2)
STDOUT << [username, password, first_name, last_name, email].join(',')
end
end
Para utilizar o script, primeiro o defini como executável:
chmod a+x formatador.rb
E em seguida o executei, passando como único parâmetro o caminho para
o arquivo de origem. Como estamos utilizando STDOUT para escrever
a saída, o resultado do script é impresso no seu terminal (ele é a
saída padrão). Você pode direcionar essa saída para um arquivo utilizando
o caracter > (no Linux/Unix da vida).
./formatador.rb entrada.txt > saida.txt
A vantagem óbvia de se utilizar STDOUT em vez de se criar outro
arquivo dentro do código-fonte é que podemos testar rapidamente o
comportamento do script ao deixar a saída ser impressa no terminal.
Embora eu tenha PHP como a minha linguagem de programação “materna”, nem pensei em escrever esse script com ela. Mas enquanto escrevia este artigo pensei “Vamos ver quanto tempo eu levo…”. E isso foi há uns 20 minutos. Isso é algo que me irrita no PHP: eu sempre tenho dificuldade pra escrever as mesmas coisas, sejam elas simples ou complexas. A ordem dos parâmetros de funções da biblioteca padrão geralmente é aleatória, você não sabe se a função leva underscore ou não, você esquece o nome dela (mas você já a utilizou tantas vezes!)… A questão é que enquanto eu levei menos de 5 minutos pra escrever a versão em Ruby, não concluí a versão em PHP por não ter paciência pra tentar descobrir o bug do programa. Para os interessados, a idéia básica era esta.
Note que ele é praticamente uma “tradução literal” do programa Ruby, feitas certas ressalvas:
- Em Ruby você não precisa fechar o arquivo que você abriu, pois o
método
File#openfaz isso pra você depois que a sua callback é executada. Em PHP você precisa fechar o arquivo explicitamente (em geral esqueço disso). - Enquanto em Ruby você itera sobre as linhas de um arquivo utilizando
o intuitivo
File#each_line(eu nunca me esqueci do nome desse método), em PHP você utiliza o medonhofgets()(já perdi a conta de quantas vezes precisei procurar por esse método na documentação oficial, pois a cada 2 meses sem utilizá-lo esqueço que ele sequer existe, hehe).
Confesso que o PHP poderia ser uma linguagem muito pior: a versão PHP do programa ficou tão compacta quanto a versão Ruby graças a vários “métodos-irmãos” entre as duas linguagens:
- Em PHP a função
list()é utilizado para permitir as atribuições simultâneas que Ruby suporta “nativamente” - Em PHP a função
explode()quebra uma string em um array. Em Ruby utilizamosArray#split - Em PHP a função
implode()constrói um array a partir de uma string. Em Ruby utilizamosArray#join
Resumo da ópera: sempre que possível utilize Ruby em vez de PHP. Sua saúde mental agradece.

November 24th, 2007 às 8:36 am
Muito legal! Vou pesquisar se o split do java tb tem uma versão para o segundo parâmetro para a junção da string restante. =)
November 24th, 2007 às 2:43 pm
Eu concordo em todos os aspectos que Ruby é superior, mas neste exemplo PHP não fica atrás não, você poderia ter utilizado a função file, que lê um arquivo inteiro para um array em php.
November 24th, 2007 às 2:53 pm
Everton, sua dica comprova meu descontentamento: não lembrava dessa função (de fato acho que nunca havia esbarrado nela), e ela realmente é muito útil. Eu só conhecia a
file_get_contents(), mas neste caso afile()realmente é melhor.Obrigado pelo comentário
November 24th, 2007 às 4:13 pm
Não por isso, estamos aqui para contribuir mesmo,
Mas eu concordo plenamente com você, no Ruby todas as funções são bem padronizadas e podem ser encontradas facilmente. Por exemplo sempre que eu quero converter alguma coisa para outra eu procuro por um função toXX, quase sempre esta la, se não estar procuro implementar utilizando o toXX.
E isso é uma das grande diferenças do Ruby, ninguém (ou quase ninguém) escreve um código Ruby com funções o nomenclatura fora do padrão utilizado pela equipe do próprio Ruby.
October 30th, 2008 às 3:47 am
Interessante mas no caso não seria mais facil e rapido utilizar awk?