Ruby On Rails

Acelerar o Rails Assets Precompile

Existem algumas poucas certezas na vida de um programador, uma delas é que o tempo de compilação tende sempre a ficar maior, conforme o projeto evolui, e para lidar com isso, precisamos de novas ferramentas ou novas formas de tratar o problema. Apesar de Ruby ser uma linguagem interpretada, todo programador Rails sofre, quando vai colocar o seu código no ar, com o tempo de compilação dos assets.

Nesse caso, o processo chamado mais precisamente de “precompile”, roda por padrão uma série de otimizações em códigos CSS e JavaScript, além da conversão de linguagens como SASS, LESS e CoffeScript, para as equivalente que seu browser é capas de entender.

Uma das coisas que mais me irritava nesse processo é que existia apenas uma única alternativa disponível no framework pra lidar com esse problema, trocar o “Componente” que realiza essa pré-compilação, por um possivelmente mais eficiente.

No entanto, nenhum existente foi pensado para ser executado em um conjunto grande de arquivos, e muito menos usando conceitos de paralelismo. E nesse ponto eu sempre achei que poderia ser algo que daria um ganho gigantesco no tempo de pré-compilação (considerando uma máquina com múltiplos cores).

Encontrei uma Gem que promete fazer algo a respeito nesse sentido. Ela faz um monkeypatch no Sprockets para que o mesmo utilize fork durante o processo e portanto, consiga utilizar todos os processadores da máquina, sem partir pra uma abordagem com threads.

Instalação:

As instruções de instalação, podem ser encontradas no projeto do Github: steel/sprockets-derailleur com a vantagem de também ter suporte para Rails 3.2

Bônus:

Existe uma discussão para melhorar o Sprockets sem a necessidade de se fazer um monkeypatch, se você também considera isso importante, contribua no ticket #308.

Bônus 2:

Eu presenciei uma melhora gigantesca no tempo de pré-compilação, quando atualizei uma aplicação legada que utilizava Rails 3.2 para 4.0 (caiu de 4 minutos para meros segundos). De início achei que pudesse ser um caso isolado e então conversei com algumas outras pessoas, que me relataram o mesmo resultado.

Então, se você está tendo problemas com isso e ainda está no Rails 3.2, mais um motivo para migrar logo.

Resultados:

Apenas para prova de conceito, escolhi uma aplicação OpenSource, para validar os ganhos. Estou utilizando o gitlabhq/gitlabhq, com a tag v7.1.0. Abaixo estão o antes e o depois (apesar de ser pouco o tempo de pré-compilação dessa aplicação, baixamos ~40%).

# Antes
bin/rake assets:precompile  0,10s user 0,02s system 1% cpu 9,124 total

# Depois
W, [2014-08-20T14:29:40.588648 #8941]  WARN -- : Initializing 8 workers
W, [2014-08-20T14:29:45.413547 #8941]  WARN -- : Completed compiling assets (5.29s)
bin/rake assets:precompile  0,10s user 0,02s system 2% cpu 5,829 total

Padrão
Ruby On Rails

Atualizando testes do RSpec 3.x automaticamente para nova sintaxe

Sempre que temos que dar manutenção em um código legado, uma coisa interessante de se fazer é atualizar as bibliotecas das quais ele depende, para aproveitar correções de segurança e melhorias, no entanto, esse processo nem sempre é simples e transparente. Eventualmente APIs se tornam deprecated e maneiras melhores de se fazer uma determinada coisa são inventadas.

O processo de refactoring pode ser duro se sua base de testes não tiver uma boa cobertura, mas quando o que precisa ser melhorado é justamente o responsável pelos testes, caímos no famoso problema: “Who watches the watchman?”

No caso estamos falando da migração do RSpec 2.x para 3.x, e aqui vai a melhor receita de bolo:

  1. Atualize primeiramente o RSpec para 2.99, esta versão vai te informar (através de Warnings) sobre todos os problemas de compatibilidade que você terá ao migrar para a 3.0 em diante, e vai te permitir consertar pró-ativamente os mais críticos.
  2. Atualize para o 3.x
  3. Instale e execute a gem Transpec para migrar as sintaxes deprecated para o novo modelo

Utilizei em um projeto que estava migrando do Rails 3.2 para 4.0 e correu sem maiores dificuldades, e o projeto ainda me gerou um template para a commit message, descrevendo tudo que foi feito! Sobra mais tempo pro café :)

Bônus: Eu optei por manter a sintaxe dos shoulda-matchers intacta, sem convertê-los de it { should ... } para it { is_expected.to ... }. Essa e outras opções podem ser feitas através de flags passadas pro transpec durante a execução. Desabilitei também o “explicit spec type”, pois uso ele dinamicamente. No meu caso o comando utilizado foi:

transpec -k oneliner -t

 

Padrão
Programação, Ruby On Rails

Por que você não deve seguir cegamente o score do Code Climate

Recentemente, houve uma discussão na lista do GURU-SC em relação a uso de patterns para satisfazer um nivel de score específico no Code Climate.

Para quem não conhece, o Code Climate é uma ferramenta para geração automática de métricas de “qualidade”. Apesar deles se intitularem uma ferramenta de Revisão de Código, não é isso que a ferramenta faz:

Code review is systematic examination (often known as peer review) of computer source code. It is intended to find and fix mistakes overlooked in the initial development phase, improving both the overall quality of software and the developers’ skills. Reviews are done in various forms such as pair programming, informal walkthroughs, and formal inspections.” – Wikipedia

Sendo pragmático, pode-se considerar o objetivo de “melhorar as habilidades dos desenvolvedores” como um objetivo complementar de “melhorar a qualidade geral do software”. Qualidade tem um significado subjetivo que pode ser visto pela ótica da robustez (um software de qualidade é aquele que nunca falha), ou pela facilidade de dar manutenção (desacoplamento, Separation of Concerns, cobertura de código, uso correto dos recursos de orientação a objetos, etc). Continuar lendo

Padrão
DevOps, Ruby On Rails

Ruby 2.0.0-p247 no Ubuntu 12.04 LTS via apt-get

Este post poderia se chamar também “Como criar pacotes Debian do Ruby 2.0.0 ou de qualquer outra versão“, já que é exatamente isso que vou ensinar.

Não se preocupe, por que não existe nenhum trabalho manual ou muito complicado, pra falar a verdade é muito mais simples do que você imagina, e com isso, você ganha uma instalação muito mais rápida no servidor de produção, seja pra uma máquina ou pra 10mil.

Se você está lendo este artigo, espero que já esteja convencido sobre por que utilizar RVM ou Rbenv em produção é uma má idéia, mas se você ainda tem dúvida, alguns argumentos para auxiliar na sua decisão:

  1. Se você não utiliza o sistema de pacotes do seu sistema operacional, você perde toda a gerência de dependências que vem com ele, e com isso, corre o risco de alguém inadvertidamente quebrar a sua instalação customizada e compilada, instalando um pacote mais antigo do que o instalado manualmente.
  2. Utilizando pacotes você consegue gerenciar facilmente atualizações, bem como garantir que todas as dependências também estão atualizadas.
  3. Compilar Ruby em produção vai degradar a performance da máquina, durante todo o processo de compilação, sem contar que será necessário instalar uma quantidade grande de dependências que não seriam normalmente utilizadas se você já tivesse o pacote compilado.
  4. Difícil automatizar, já que você não tem muito controle sobre o que pode acontecer durante um processo de compilação. Uma compilação pode falhar em uma das máquinas e você dificilmente vai ficar sabendo disso, se esse procedimento for ser executado em muitas máquinas ao mesmo tempo e de forma regular.
  5. Desperdício de recurso ter compilar a mesma coisa em várias máquinas.

Se você ainda achar que os argumentos acima não são suficientes, talvez a facilidade de se gerar o pacote possa te convencer o contrário.

Continuar lendo

Padrão
Ruby On Rails, Tutoriais, Ubuntu

Instalação do Ruby 2.0.0-p195 no Ubuntu 12.04+ sem RVM e Rbenv

Se você estava aguardando uma patch release do Ruby 2.0 para começar a utilizar ele em produção, a hora é esta. Com o lançamento a poucos dias do 2.0.0-p195 e do lançamento dos pacotes pela Brightbox, ficou mais fácil impossível de instalar em produção, sem precisar das soluções alternativas do RVM e do Rbenv.

Este artigo é uma atualização do artigo anterior: Instalação do Ruby 1.9.3 sem RVM ou Rbenv no Ubuntu 12.04, para mais detalhes consulte-o.

Note que vamos utilizar para essa instalação o repositório experimental, o que significa em outras palavras: “não utilize para sistemas que possuam necessidade crítica de estabilidade”.

Continuar lendo

Padrão
Ruby On Rails

Sobre CMS e Ruby on Rails

Alguém havia perguntado na comunidade Ruby on Rails Brasil a algum tempo atrás sugestões sobre CMS ou código de “Blogs” escrito em Rails. Em uma das minhas divagações filosóficas deste final de semana, estava chegando a uma conclusão sobre o por que nenhum CMS feito em Rails realmente decolou (a ponto de ser um concorrente a altura do WordPress).

Posso citar algumas coisas aqui que valem ser ditas:

  1. Nenhuma empresa patrocinando (este é o principal motivo na minha opnião… projetos ambiciosos sem uma empresa por trás pagando horas de desenvolvimento, tendem a falhar)
  2. Já existe o WordPress (ou seja, qualquer coisa que seja menos atraente que ele, não vai conseguir gerar massa crítica e convencer pessoas a desenvolver temas, plugins etc).
  3. Difícil customização (este aqui é o ponto que mais pesa, se eu já não estou usando o WordPress, é por que provavelmente eu preciso customizar o projeto e não quero “sujar as mãos” com código pouco estruturado em PHP).

Nessa linha, fiquei imaginando um pouco sobre quais características um projeto de CMS poderia ter que conseguisse superar as soluções existentes e ganhar tração suficiente para conseguir seu espaço ao sol. Continuar lendo

Padrão
Ruby On Rails, Ubuntu

Instalação do Nginx + Passenger no Ubuntu 12.04 via apt-get

Este artigo é uma continuação do artigo anterior, Instalação do Ruby 1.9.3 sem RVM ou Rbenv no Ubuntu 12.04.

Se você ainda não seguiu os passos de instalação sugeridos no artigo anterior, faça-os, já que eles são necessários para que os passos seguintes funcionem conforme esperado.

Como explicado no artigo anterior, estamos usando o ppa da Brightbox, que além de nos fornecer uma versão atualizada e otimizada do Ruby, também fornece uma compilação do nginx com passenger, integrados com ruby 1.8.7 ou 1.9.3.

A instalação é feita via apt-get:

sudo apt-get install nginx passenger-common1.9.1

Feito isto, é necessário verificar apenas o arquivo de configurações do nginx e descomentar as duas linhas mencionadas no trecho de configuração do passenger:

  ##
  # nginx-passenger config
  ##
  # Uncomment it if you installed nginx-passenger
  ##

  #passenger_root /usr/lib/phusion-passenger;
  #passenger_ruby /usr/bin/ruby;

Com isso você tem uma instalação funcional do nginx com passenger embutido, e precisa agora apenas gerar uma configuração de virtual host.

Este ultimo passo é o que de fato vai apontar uma “pasta” do seu servidor, para ser disponibilizada pelo nginx quando alguém acessar um determinado domínio.

Vamos colocar o arquivo em /etc/nginx/sites-enabled e reiniciar o servidor (sudo service nginx restart):

server {
    listen 80;
    server_name  meusite.example.com;
    root /var/www/meusite.example.com/public; # <--- apontar pra pasta 'public'
    passenger_enabled on;
}

Está pronto. Nginx + Passenger atendendo requisições em um virtualhost, sem precisar do RVM, do rbenv ou de compilar na mão passenger ou alguma versão do ruby.

Padrão
Ruby On Rails

Instalação do Ruby 1.9.3 sem RVM ou Rbenv no Ubuntu 12.04

Muitas pessoas acabam se frustrando com a instalação do Ruby / Rails quando utilizam o RVM ou o Rbenv, e principalmente na utilização desses dois para uma máquina em produção.

O motivo principal das muitas dores de cabeça é que ambas soluções funcionam alterando variáveis de ambiente da sua shell para disponibilizar algo que o sistema operacional deveria estar fazendo nativamente.

Existem situações em que usar o RVM, principalmente em ambiente de desenvolvimento é desejável, permitindo trocar de versões rapidamente e testar o código, patches de seguranças. Este artigo não quer desmerecer os usos válidos do RVM, mas se ele está te dando dores de cabeça, talvez uma solução mais simples seja o caso.

A solução proposta aqui é utilizar os padrões que o Ubuntu / Debian definiram, ou seja: Debian Packages para instalar o ruby e Update Alternatives (links simbólicos) para trocar entre as versões de ruby disponíveis.

A instalação é composta de alguns poucos comandos. Se você estiver utilizando um ubuntu server, existe um pacote adicional que precisa ser instalado, pois o mesmo não vem instalado por padrão:

sudo apt-get install python-software-properties

Para Ubuntu 12.10+ utilize o comando abaixo:

sudo apt-get install software-properties-common

O comando acima disponibiliza o “add-apt-repository“.

Para prosseguir com a instalação, vamos adicionar um ppa mantido pela Brightbox, uma empresa de hosting especializada em Ruby, do Reino Unido, e realizar a instalação dos pacotes necessários:

sudo apt-add-repository ppa:brightbox/ruby-ng 
sudo apt-get update 
sudo apt-get install build-essential ruby rubygems ruby-switch

Os comandos acima, instalam a versão mais atualizada do ruby 1.8.7 e o comando “ruby-switch” que será responsável por trocar a versão do ruby sendo utilizada no momento, da mesma forma como o RVM e o Rbenv fazem.

Para instalar a versão 1.9.3, você deve rodar o comando a seguir (note que 1.9.1 é um padrão de numeração de versão utilizada pelo Debian, mas acredite, estamos instalando a 1.9.3)

sudo apt-get install ruby1.9.1-full

E por fim, para alterar entre as versões:

sudo ruby-switch --set ruby1.9.1
sudo ruby-switch --set ruby1.8

 Bonus: ao utilizar a versão 1.9.3 disponibilizada pela Brightbox, você estará utilizando uma versão otimizada da mesma, que inclui entre outras coisas, as seguintes modificações:

Este ultimo é o meu favorito, quem ainda não leu o artigo linkado acima, deveria. O novo garbage colector da 2.0 em um resumo simplista, vai economizar muita memória no servidor em comparação com a versão 1.9.3, no entanto, graças a esse backport, você ganha a mesma melhoria já na 1.9.3

Atualizado 23/05/2013: Fiz alguns ajustes no artigo para incluir correções necessárias para funcionar também no Ubuntu 12.10+. Agora sugiro instalar o pacote “ruby-1.9.1-full” que resolverá a falta do “mkmf”que algumas gems necessitam.

Padrão
Ruby On Rails, Ubuntu

Nginx + Passenger no Ubuntu com Upstart

Se você trabalha sério com web, provavelmente já teve que instalar o Nginx para alguma coisa. No Ubuntu a instalação é fácil e simples:

apt-get install nginx

Porém, os pacotes não estão tão atualizados quanto deveriam e, pra piorar, devido a arquitetura do Nginx, não trabalha com módulos plugáveis dinamicamente, como o Apache. Dessa forma a única alternativa de ter o Nginx com Passenger e em versão atualizada, é através do instalador disponível nos Rubygems.

A instalação passa pelos seguintes passos:

gem install passenger
passenger-install-nginx-module

Ao executar a instalação do passenger, basta seguir as instruções e instalar os pacotes que forem necessários. Ao concluir, você terá uma instalação atualizada do Nginx com suporte ao Passenger.

Neste ponto só falta configurar o Upstart para cuidar de iniciar o Nginx toda vez que o servidor for iniciado:

/etc/init/nginx.conf

# nginx

description "nginx http daemon"
author "George Shammas &lt;georgyo@gmail.com&gt;"

start on (filesystem and net-device-up IFACE=lo)
stop on runlevel [!2345]

env DAEMON=/opt/nginx/sbin/nginx
env PID=/var/run/nginx.pid
expect fork
respawn

pre-start script
        $DAEMON -t
        if [ $? -ne 0 ]
                then exit $?
        fi
end script

post-stop script
    start-stop-daemon --stop --pidfile $PID --name nginx --exec $DAEMON --signal TERM
end script

exec $DAEMON

Uma observação importante, para que funcione corretamente o script acima, é necessário que o pid esteja configurado corretamente no /opt/nginx/conf/nginx.conf, conforme exemplo a baixo:

pid /var/run/nginx.pid;
Padrão