Arquivo da tag: rubygems

Você sabia que dá para usar versões diferentes de ruby na mesma máquina ?

RVM ou Ruby Version Manager é o gerenciador de versões Ruby.

Com ele você pode rodar projetos com rubys diferentes (exemplo: com a versão 1.8.7 e 1.9.3) mantendo os ambientes e as gems instaladas isoladas.

Conheça mais sobre o RVM em: https://rvm.io/

Ou se preferir, pode ir direto para a página de instalação em https://rvm.io/rvm/install/

Um outro bom exemplo de uso do RVM, não é só a utilização de multiplos Rubys, e sim a separação que ele faz entre os projetos.

Você pode criar com o RVM um “Gemset”, que é um grupo isolado onde se instalada as gem de seu projeto. Com isso você pode usar o mesmo ruby, e ter mais de um gemset configurado.

Share

Ubuntu 11.10 com Ruby on Rails + Nginx + Mysql de forma simples

Andei procurando na internet por algum script para fazer uma instalação mais “automatizada” de um ambiente Ruby on Rails numa máquina virtual (VPS) rodando Ubuntu 11.10

Depois de pesquisar muito, só encontrei referências detalhadas  para ubuntu 10.* ou então alguns blogs sugerindo algumas linhas de comando apenas.

Como eu já estava terminando um projeto de um site e precisava de um ambiente de produção, resolvi fazer um script (em bash), onde eu tivesse o controle de tudo que iria acontecer de forma segura e eficaz.

O script está disponível no meu github, use como quiser =)

Lembrando que só testei no Ubuntu 11.10, a instalação instala e configura o seguinte:
– Ruby 1.9.2-p290
–  Nginx Upload Module 2.2.0
– Nginx 1.1.12 
– iptables para as portas principais de ssh(22), http(80), https(443), dns(53)
– Mysql (versão estável do apt-get do ubuntu)
– Postfix (versão estável do apt-get do ubuntu)
– Gem Bundler (última versão pelo rubygems)

Com isso, basta configurar o domínio da sua aplicação corretamente na configuração do nginx, fazer o deploy e ser feliz! =)

Link do projeto: https://github.com/rafaelbiriba/Ubuntu-VPS-Builder 

Abaixo segue uma cópia do código que eu coloquei no git assim você pode tirar suas dúvidas pelos comentários… Caso decida usar o script, baixe ele pelo link do github. Não use o código abaixo pois o mesmo pode já estar desatualizado!

Modo de usar no servidor:
$ chmod +x vps_builder.sh
$ ./vps_builder.sh seudominio.com 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#!/bin/bash
# "Automated VPS Setup for Ubuntu 11.10 - Rails with Nginx"
#
# Created by: Rafael Biriba - www.rafaelbiriba.com - [email protected]
# https://github.com/rafaelbiriba/Ubuntu-VPS-Builder/
#
# USAGE:
#
# $ chmod +x vps_builder.sh
# $ ./vps_builder.sh yourdomain.com"
 
echo "Updating before all"
apt-get update && apt-get upgrade -y
 
echo "Set Hostname"
 
echo $1 > /etc/hostname
echo "127.0.0.1 $1" >> /etc/hosts
hostname -F /etc/hostname
 
echo "Set Timezone"
 
ln -sf /usr/share/zoneinfo/America/Sao_Paulo /etc/localtime
 
echo "Install Essencials"
 
apt-get install build-essential zlib1g-dev libreadline6-dev libssl-dev wget git-core sudo -y
 
echo "Install Ruby 1.9.2"
 
mkdir ~/tmp && cd ~/tmp
wget http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.2-p290.tar.gz
tar xzvf ruby-1.9.2-p290.tar.gz
cd ruby-1.9.2-p290
./configure
make
make install
cd ~
rm -rf ~/tmp
 
echo "Install Passenger and Nginx"
 
mkdir ~/tmp && cd ~/tmp
wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.21.tar.gz
tar xzvf pcre-8.21.tar.gz
cd pcre-8.21
./configure && make && make install
cd ~/tmp
 
wget http://nginx.org/download/nginx-1.1.12.tar.gz
wget http://www.grid.net.ru/nginx/download/nginx_upload_module-2.2.0.tar.gz
tar xzvf nginx-1.1.12.tar.gz
tar xzvf nginx_upload_module-2.2.0.tar.gz
 
gem install passenger
apt-get install libcurl4-openssl-dev -y
passenger-install-nginx-module --prefix=/opt/nginx --nginx-source-dir=/root/tmp/nginx-1.1.12 --extra-configure-flags=--add-module='/root/tmp/nginx_upload_module-2.2.0'
#passenger-install-nginx-module --auto --auto-download
cd ~
rm -rf ~/tmp
 
cd ~
wget https://raw.github.com/rafaelbiriba/Ubuntu-VPS-Builder/master/ubuntu_11-10_desktop/nginx-init.sh
cp nginx-init.sh /etc/init.d/nginx
rm nginx-init.sh
chmod +x /etc/init.d/nginx
/usr/sbin/update-rc.d -f nginx defaults
/etc/init.d/nginx start
 
echo "Configure iptables"
 
apt-get install iptables
 
tee /etc/init.d/firewall <<ENDOFFILE
#!/bin/bash
 
start(){
# Accepting all connections made on the special lo - loopback - 127.0.0.1 - interface
iptables -A INPUT -p tcp -i lo -j ACCEPT
 
# Rule which allows established tcp connections to stay up
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
 
# SSH:
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
 
# DNS:
iptables -A INPUT -p tcp --dport 53 -j ACCEPT
iptables -A INPUT -p udp --dport 53 -j ACCEPT
 
# HTTP e HTTPS:
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
 
# Block others ports
iptables -A INPUT -p tcp --syn -j DROP
iptables -A INPUT -p udp --dport 0:1023 -j DROP
 
}
stop(){
iptables -F
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
}
 
case "\$1" in
"start") start ;;
"stop") stop ;;
"restart") stop; start ;;
*) echo "start or stop params"
esac
ENDOFFILE
 
chmod +x /etc/init.d/firewall
update-rc.d firewall defaults 99
/etc/init.d/firewall start
 
echo "Install MySQL"
 
apt-get install mysql-server mysql-client libmysqlclient-dev -y
 
echo "Install postfix"
 
# Install type: Internet Site
# Default email domain name: example.com
apt-get install postfix mailutils telnet -y
/usr/sbin/update-rc.d postfix defaults
/etc/init.d/postfix start
 
echo "Install gem bundler"
 
gem install bundler
 
echo "VPS Setup Complete"

Qualquer dúvida, estamos aí para trocar ideias 😉

___________________________________________________

Atualização 1 – 07/fev/2012:

Agradeço ao leitor Laércio pelo contato via email, reportando um problema, onde se o ubuntu estiver muito desatualizado, o script não roda direito. Com isso adicionei lá no github e no exemplo acima os comandos apt-get update e apt-get upgrade para atualizar o ubuntu antes de fazer qualquer coisa. Obrigado mais uma vez Laércio !

Share

Raptcha: Um captcha simples para aplicações Rails

 

Humor: Robôs lendo o captcha

Captcha é um teste de desafio cognitivo, utilizado como ferramenta anti-spam. O que acontece é que um script automatizado (um robô), não consegue ler o texto embaralhado nas imagens. Isso faz com que seja uma excelente ferramenta para combater o spam ou prevenir que scripts tenham acesso a determinadas áreas.

Recentemente tive que procurar uma gem (um pacote do rubygems) de captcha para minha aplicação rails, mas que fosse a mais simples possível e sem nenhuma dependência externa.

Vi que a mais utilizada é a gem recaptcha, que utiliza a estrutura da API do google de captcha (google.com/recaptcha). Para resolver o meu problema ela não serve, já que o meu projeto vai rodar em máquinas sem acesso a internet.

Então ao continuar a busca por uma boa gem de captcha, recebi a recomendação de usar o Raptcha.

O Raptcha é realmente muito simples de configurar e de usar. Ele usa o Image Magick para renderizar as imagens em tempo real.

Em alguns casos isso pode ser um problema, mas no caso da minha aplicação, não havia necessidade de cachear as imagens.

Ao lado temos um exemplo do uso do raptcha.

Você pode conferir a documentação de instalação pelo link: https://github.com/ahoward/raptcha

Quando estava fazendo os meus testes, tive dificuldade para fazer as letras do captcha aparecer. Se isso acontecer, tente instalar o pacote GhostScript. Se você estiver usando o ubuntu, o imagemagick e o ghostscript tem no synaptic. Se você usa macbook, ambos os pacotes podem ser instalados pelo repositório do brew (não sei se tem no ports).

Um outro problema que eu tive que resolver, foi implementar o botão de gerar outro captcha. Infelizmente o raptcha não da suporte nativo a isso. Mas pode ser facilmente resolvido usando Ajax. O que eu fiz foi colocar no controller um render partial como mostra o código a seguir:

1
2
3
4
5
6
7
8
9
10
11
class RaptchaController < ApplicationController
 
  def index
    Raptcha.render(controller=self, params)
  end
 
  def get_form
    render :partial => "form"
  end
 
end

E no partial “form” ficou assim:

1
<%= raw Raptcha.input %>

Dessa forma, a chamar a url: http://localhost:3000/raptcha/get_form obtemos o retorno de todo o form do raptcha:

1
2
3
4
5
6
7
8
<div class="raptcha">
   <img class="raptcha-image" src="/raptcha?e=DaROXGWrRTrLdYXmJ05iKg" alt="Imagem de validação" width="242" height="68" />
 
   <label><img id="captcha-reload" title="Recarregar imagem" src="/images/mini-reload.gif" alt="" />Digite as letras acima:</label>
 
   <input class="raptcha-input box" name="raptcha[t]" type="textarea" />
   <input class="raptcha-word" name="raptcha[w]" type="hidden" value="DaROXGWrRTrLdYXmJ05iKg" />
   <input class="raptcha-timebomb" name="raptcha[b]" type="hidden" value="nEZ-sQYpOFC2YIE2qhAjeQ" /></div>

Então basta você colocar uma ação no botão #captcha-reload e obter um novo form por ajax e substituir o form antigo na página de sua aplicação. Fazendo assim, você poderá recarregar o seu captcha quantas vezes precisar…

Então é isso… Se você precisa de uma solução simples para o captcha em seu projeto, experimente o Raptcha usando as dicas acima… 😉

Share

Net-SFTP: Calculando o progresso do upload

Estou escrevendo esse post, para complementar o post sobre o timeout do net-sftp, onde fiquei devendo essa a solução de calculo do progresso…

Para obter o progresso durante o upload, você precisa usar o callback do método upload! e jogar numa variável os valores do tamanho local e do tamanho do arquivo no destino.

Vejamos um pequeno exemplo, retirado da documentação:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
require 'rubygems'
require 'net/sftp'
Net::SFTP.start('192.168.0.2', 'rafaelbiriba', {:password => 'teste', :timeout => 3}) do |sftp|
  sftp.upload!("/Users/rafaelbiriba/Projects/temp/video-teste-sftp.mp4", "/home/rafaelbiriba/video-teste-sftp.mp4") do |event, uploader, *args|
    case event
    when :open then
      # args[0] : file metadata
      puts "starting upload: #{args[0].local} -> #{args[0].remote} (#{args[0].size} bytes}"
    when :put then
      # args[0] : file metadata
      # args[1] : byte offset in remote file
      # args[2] : data being written (as string)
      puts "writing #{args[2].length} bytes to #{args[0].remote} starting at #{args[1]}"
    when :finish then
      puts "all done!"
    end
  end
end

No exemplo acima podemos verificar:

  • Ao abrir a conexão (when open), podemos chamar args[0].size e obter o tamanho total do arquivo
  • Durante a transferência (when put), ao chamar args[1] podemos obter o tamanho do arquivo remoto

Com isso, quando o tamanho total do arquivo for igual ao tamanho do arquivo remoto, então o upload estará terminado (100%). Para obter as porcentagens, basta fazer o cálculo.

Confira no exemplo abaixo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
require 'rubygems'
require 'net/sftp'
@total_size = 0
@remote_size = 0
@current_progress = 0
 
def update_sftp_progress
  progress = (@remote_size*100)/@total_size)
  if @current_progress < progress then
    @current_progress = progress
    puts "Uploading: #{@current_progress}%" 
  end
end
 
Net::SFTP.start('192.168.0.2', 'rafaelbiriba', {:password => 'teste', :timeout => 3}) do |sftp|
 sftp.upload!("/Users/rafaelbiriba/Projects/temp/video-teste-sftp.mp4", "/home/rafaelbiriba/video-teste-sftp.mp4") do |event, uploader, *args|
   case event
     when :open then
       @total_size = args[0].size
       puts "Starting upload..."
     when :put then
       @remote_size = args[1]
       update_sftp_progress
     when :finish then
       puts "Finished!"
     end
   end
end

Toda vez que o arquivo no destino for incrementado, o evento (:put) será disparado, chamando o método update_sftp_progress.

Nesse método é feito o cálculo da porcentagem(ver no exemplo acima). Ao invés de imprimir a porcentagem(com puts), você também pode salvar no banco de dados, ou utilizar o valor para fazer uma barra de progresso.

Espero ter ajudado, 😉

Share

Net-sftp: Solução para timeout durante o upload

Desenvolvendo um script em ruby para upload de arquivos, utilizando a gem net-sftp, acabei encontrando um problema. A falta de timeout durante a transferência.

Decidi escrever esse post, para compartilhar a minha solução e também receber opniões e outras soluções para o problema. Fiz algo parecido quando escrevi o post sobre o cron de 15 em 15 segundos e obtive resultados bem legais.

Introdução ao problema
A gem net-sftp é bastante utilizada em scripts ruby que requerem alguma transferência de arquivo utilizando uma conexão segura, como por exemplo, upload, download, criação de diretórios e etc… Utilizando a gem net-ssh para estabelecer essa conexão.

Primeiramente, vamor ver um exemplo do problema:

1
2
3
4
5
require 'rubygems'
require 'net/sftp'
Net::SFTP.start('192.168.0.2', 'rafaelbiriba', {:password => 'teste', :timeout => 3}) do |sftp|
  sftp.upload!("/Users/rafaelbiriba/Projects/temp/video-teste-sftp.mp4", "/home/rafaelbiriba/video-teste-sftp.mp4")
end

O código acima faz o upload de um arquivo de mais de 400 Mb. Se durante o upload houver um problema na sua conexão, o upload fica “esperando” a rede voltar, o que é um problemão, pois ele trava a execução do script, sem dar nenhum sinal de vida.

De acordo com a documentação do net-sftp, você pode utilizar o método “upload” no lugar de “upload!” para não travar a execução do script. Mas ainda sim o problema continua. Fazendo isso, você vai precisar rodar um loop até que o upload termine. Ou seja, se a conexão cair, o método só vai terminar(e sair do loop) quando a conexão voltar. Então essa opção foi logo descartada.

O problema mesmo só acontece quando há perda de conexão depois que a sessão inicia. (O parâmetro :timeout apenas estabelece o limite de espera para iniciar a sessão e não durante a transferência dos arquivos.)

Se o net-sftp / net-ssh aceitasse a opção “ServerAliveInterval” (Parametro de configuração do ssh), ele iria verificar a conexão durante a transferência e ao alcançar o limite (“ServerAliveCountMax”) seria disparado o timeout. Infelizmente, de acordo com a documentação do net-ssh esses parâmetros não estão disponíveis.

Seguindo com a leitura e busca pela solução na documentação do net-sftp, achei uma possível pista para encontrar a solução:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
require 'rubygems'
require 'net/sftp'
Net::SFTP.start('192.168.0.2', 'rafaelbiriba', {:password => 'teste', :timeout => 3}) do |sftp|
  sftp.upload!("/Users/rafaelbiriba/Projects/temp/video-teste-sftp.mp4", "/home/rafaelbiriba/video-teste-sftp.mp4") do |event, uploader, *args|
    case event
    when :open then
      # args[0] : file metadata
      puts "starting upload: #{args[0].local} -> #{args[0].remote} (#{args[0].size} bytes}"
    when :put then
      # args[0] : file metadata
      # args[1] : byte offset in remote file
      # args[2] : data being written (as string)
      puts "writing #{args[2].length} bytes to #{args[0].remote} starting at #{args[1]}"
    when :finish then
      puts "all done!"
    end
  end
end

Acima temos um exemplo simples retirado da documentação para o controle do progresso de upload.

Quando o upload inicia, o case recebe o evento “:open” onde podemos obter o tamanho total do arquivo e logo em seguida recebe os eventos “:put” onde é possível verificar  o quanto (em bytes) do arquivo já foi enviado, possibilitando assim a criação da porcentagem do upload.

Como o foco aqui não é mostrar como obter o progresso (posso mostrar isso exclusivamente em outro post calculando o progresso durante o upload), não vou entrar muito em detalhes sobre isso. O que realmente inporta nesses eventos são que durante o upload (:put), ao perder a conexão, nenhum evento é disparado, ou seja, o script não tem como sabe que a conexão caiu e a execução fica travada no upload.

Minha solução:

Depois de todo esse estudo detalhado sobre o problema, comecei a pensar numa possível solução. Eu precisava utilizar alguma coisa que pudesse verificar e dar timeout no upload caso ele parasse de responder/transferir.

Foi então que pesquisei, testei e implementei o rufus-scheduler*,  um agendador de tarefas que roda dentro do script ruby(mas numa outra thread), onde posso definir um intervalo de execução para executar alguma coisa, como se fosse um cron. ( *Sugestão do @vicentemundim )

Então a solução foi: Assim que o upload começar, eu defino um tempo de 10 segundos para ele executar uma tarefa com “raise exception”. Então toda vez que o upload responder ao evento (:put), informando que conseguiu subir mais um trecho do arquivo, eu reseto o tempo de execução da tarefa e defino novamente em 10 segundos. Fazendo isso, quando a conexão cair ou o upload travar por algum motivo, ele vai parar de responder ao evento “:put”, e então a tarefa agendada para 10 segundos vai disparar o raise, interrompendo a execução do script.

Depois de alguns testes, tanto de desempenho quanto de falhas, percebi que essa resolução serviu perfeitamente. Segue o exemplo do código utilizado:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
require 'rubygems'
require 'rufus/scheduler'
require 'net/sftp'
 
@job = nil
@scheduler = Rufus::Scheduler::PlainScheduler.start_new  
def @scheduler.handle_exception (job, exception)
  abort(exception.message)
end
 
def job_scheduler
  @job.unschedule unless @job.nil?
  @job = @scheduler.every "10s" do
    raise "SFTP Connection Lost or upload freezed timeout"
  end    
end
 
Net::SFTP.start('192.168.0.2', 'rafaelbiriba', {:password => 'teste', :timeout => 3}) do |sftp|
  sftp.upload!("/Users/rafaelbiriba/Projects/temp/video-teste-sftp.mp4", "/home/rafaelbiriba/video-teste-sftp.mp4") do |event, uploader, *args|
    case event
    when :open then
      puts "starting upload: #{args[0].local} -> #{args[0].remote} (#{args[0].size} bytes}"
      job_scheduler
    when :put then
      puts "writing #{args[2].length} bytes to #{args[0].remote} starting at #{args[1]}"
      job_scheduler
    when :finish then
      puts "all done!"
     @job.unschedule unless @job.nil? 
    end
  end
end

Quando o upload inicia (:open) e durante a transferência (:put), ele chama o método job_scheduler que é responsável por resetar a tarefa anterior(se houver) e agendar uma nova com timeout de 10 segundos.

Conforme expliquei acima, se o upload travar, o tempo limite de 10 segundos é alcançado e uma exceção é disparada.

Como o agendador do rufus roda em outra thread, qualquer exceção disparada é capturada e tratada pelo próprio rufus, fazendo com que a execução do script continue. Então, sobrescrevi o método (handle_exception) e ao receber a exceção, gero um abort que irá interromper todo o script.

Infelizmente, são poucos os sites relacionados sobre esse assunto, o que dificultou bastante a busca e o desenvolvimento. Mesmo assim, acredito ter resolvido o problema com uma solução bem razoável.

Já falei em cima, mas vale ressaltar:
“Decidi escrever esse post, para compartilhar a minha solução e também receber opniões e outras soluções para o problema. Fiz algo parecido quando escrevi o post sobre o cron de 15 em 15 segundos e obtive resultados bem legais.”

Estou pensando em tentar solucionar isso direto no código do net-sftp e quem sabe mandar um patch para o autor. De qualquer forma, fico no aguardo de qualquer comentário e/ou soluções melhores.

handle_exception
Share

Cloud Crowd: A primeira action

cloud-crowd

Cloud Crowd é um controlador de filas para processamento paralelo, desenvolvido em ruby. Pode ser utilizado em Encoding de video, migração de arquivos e bancos de dados, redimensionamento de imagens e etc…

Uma explicação rápida: Em uma máquina você levanta o server, onde é gerenciado a fila (criação, exclusão, status das tarefas e etc…). Em outras máquinas você levanta o node, onde as terefas serão recebidas e executadas. Ao terminar, o node informa ao server, liberando-se para receber outra tarefa.

Essa semana comecei a desvendar os benefícios do Cloud Crowd, principalmente para encoding paralelo de vídeo. Mas antes, tive que entender como ele funciona e o que tem para nos oferecer.

Então, acompanhando o “tutorial” em http://wiki.github.com/documentcloud/cloud-crowd/writing-an-action, escrevi uma pequena action:

class HelloWorld < CloudCrowd::Action
   def process
      Thin::Logging.log("HelloWorld :: -- criando arquivo #{input}!")
      `touch #{input}`
      0
   end
end

Você passa um nome qualquer, e o script cria um arquivo em branco. Simples !?, Mas serviu bem para meus primeiros testes.

Também aproveitei e usei o log do Thin que é o servidor que o Cloud Crowd levanta, para registrar o evento de dentro da action… Isso significa que as mensagens de log da minha action foram registradas no arquivo de log do node que a executou… Se preferir você pode utilizar o Logger do Rails. Como foi apenas um experimento, utilizei o do Thin mesmo.

Cadastrando tarefas:

Para começar a utilizar sua action,  você precisa postar um JSON com as informações necessárias no server, para cadastrar uma tarefa. (Não preciso lembrar que o server e algum node deve estar rodando, certo ?)

Para isso, crie um script ruby, ou rode pelo irb os comandos*:

require 'rubygems'
require 'restclient'
require 'json'
RestClient.post('http://localhost:9173/jobs',{:job => { 'action' => 'hello_world' , 'inputs' => ['/home/rafael/arquivo_teste1', '/home/rafael/arquivo_teste2']}.to_json})

Considerando que o server está rodando na máquina que rodou o script. Caso contrário, altere o localhost pelo ip do Server. E os arquivos são criados (pelo comando “touch”) na máquina que roda o Node. Para fins de teste e desenvolvimento, é possível rodar o server e o node na mesma máquina, já que eles sobem em portas diferentes…

Então é isso… Você já pode paralelizar qualquer tarefa. Basta escrever suas próprias actions… 😉

 

Share

Ruby: Alternativas para require ‘rubygems’

ruby-logo-justruby

Baseado no comentário de Guilherme Chapiewski encontrado em https://rafaelbiriba.com/2009/04/13/ruby-require-rubygems.html, resolvi postar alternativas para suprir essa necessidade do require ‘rubygems’ e porque é errado utilizá-lo !

Primeiramente, vamos para a pergunta que originou este post:
O que há de errado em utilizar require ‘rubygems’ no meu script ?

Bom, analisando o exemplo que eu dei no post do require rubygems, transcrito logo abaixo, onde se você quiser utilizar o pacote “hpricot”, instalado pelo comando gem install hpricot, o código não irá rodar, retornando um erro referente ao rubygems. Usando o require ‘rubygems’ o problema é resolvido, mas não está correto. O motivo é bem simples. Primeiro vamos ver o código em questão:

require 'hpricot' 
require 'open-uri' 
meuXml = Hpricot.XML(open("http://www.exemplo.com/exemplo.xml"))

Concordam comigo que o código acima, é uma simples aplicação em ruby ? O que eu quero dizer é que você pode instalar o hpricot de várias maneiras diferentes ! Por exemplo, acessando o link: http://wiki.github.com/why/hpricot/installing-hpricot, você pode observar que o Hpricot pode ser instalado sem o Rubygems. Sendo assim, ao usar o require “rubygems” em um máquina que não tem o rubygems instalado, vai dar problema na execução !

Então o que fazer se eu instalei o Hpricot pelo rubygems ? Simples…

Você pode facilmente rodar o seu script incluindo -rubygems na linha de comando, conforme o exemplo abaixo:

ruby -rubygems meu_script.rb

Isso fará rodar o pacote rubygems antes de executar sua aplicação meu_script.rb

Fonte: http://gist.github.com/54177

Bom, então é isso.

Share

Ruby: require ‘rubygems’

ruby-logo-justruby

Essa semana estive escrevendo alguns códigos usando Ruby on Rails, e encontrei um problema, que demorei um pouco para descobrir sua solução, mas no fim se tratava de algo muito simples e lógico.

Ao instalar o Rails e qualquer outro pacote pelo rubygems ( gem install hpricot, por exemplo), para importar esse pacote no código, é necessário importar a biblioteca do rubygems primeiro.

Manual do RubyGems ( http://docs.rubygems.org/read/book/1 ).

Na prática, eu estava utilizando o código abaixo:

require 'hpricot' 
require 'open-uri' 
meuXml = Hpricot.XML(open("http://www.exemplo.com/exemplo.xml"))

Este codigo abre uma URL, captura seu XML e armazena o conteúdo em uma variável ( string ).

Porém, isso só é possível se incluir a biblioteca do rubygems. Verifique o código abaixo, desta vez, funcionando:

require 'rubygems'
require 'hpricot'
require 'open-uri' 
meuXml = Hpricot.XML(open("http://www.exemplo.com/exemplo.xml"))

 

Bom, então é isso !
—————–
Baseado no comentário recebido depois da publicação deste Post, visite também:
https://rafaelbiriba.com/2009/04/29/ruby-require-rubygems-alternativas.html

Share