Atualizando seu projeto para uma nova versão do Rails
Leia em 6 minutos
Toda vez que você inicia um novo projeto Rails, normalmente a última versão estável é utilizada. Você desenvolve o projeto, processo esse que pode levar algum tempo (semanas ou meses) e, com uma certa frequência, logo seu projeto se torna impossível de migrar para uma nova versão do Rails. Por que isso acontece? Como você pode evitar esta armadilha?
Um passo de cada vez
A primeira etapa para uma atualização ter sucesso é fazer tudo em pequenas etapas. Sua aplicação está rodando na versão 3.2.21 e você quer atualizar para o Rails 4.2.0? Sem problemas! Apenas saiba que é muito mais fácil fazer isso se você atualizar primeiro para 4.0.13, depois para 4.1.9 e só então fazer o upgrade para Rails 4.2.0.
Parece trabalhoso? Sim, mas só assim você conseguirá atualizar o seu projeto seguindo a estrutura utilizada por esta nova versão. Além disso, você conseguirá modificar seu projeto para adequar as novas funcionalidades que foram adicionadas (ou removidas).
Entendendo o versionamento do Rails
O Rails segue um versionamento inspirado no SemVer. O versionamento X.Y.Z
tem a seguinte representação:
- Patch
Z
: Somente correções de falhas, sem mudanças na API ou novas funcionalidades, exceto se isso for necessário para uma correção de segurança. - Minor
Y
: Novas funcionalidades. Também pode conter mudanças na API. Quebra APIs que tiveram notificação de deprecation em versões minor e major anteriores. - Major
X
: Novas funcionalidades, com provável mudança de API. A diferença entre uma versão minor e major do Rails está na quantidade de quebras de API.
Quando falamos em fazer o upgrade de uma versão do Rails, normalmente nos referimos a mudança de major e minor. Logo, seria a atualização de 3.1 para 3.2, de 3.2 para 4.0, e assim vai.
Para saber qual a versão mais recente do Rails, visite a página do projeto no Rubygems.org.
Quando uma nova versão está para ser lançada, são disponibilizadas versões beta e release candidate. Isso permite que os desenvolvedores testem estas versões e reportem coisas que deixaram de funcionar mas que não deveriam. Isso permite ter lançamentos mais sólidos e com menos regressões.
Atualizando o código do projeto
Sempre que você atualizar o seu projeto para uma nova major version, lembre-se de executar o comando rake rails:update
. Isso irá atualizar arquivos gerados pelo Rails e criar novos arquivos utilizados por aquela versão.
Se você faz como a maioria dos desenvolvedores e altera os arquivos config/application.rb
e environments/*.rb
diretamente, saiba que essa etapa pode demorar muito mais tempo. Isso porque você terá que analizar a diferença entre o código gerado pelo Rails e suas modificações. Em vez de perder tempo com isso, aqui vai uma regra: não modifique estes arquivos; prefira definir estas configurações em initializers.
Quando você tem configurações diferentes para cada ambiente, você precisará fazer isso condicionalmente. Veja, por exemplo, como você pode configurar o ActionMailer para os ambientes de desenvolvimento e produção.
# config/initializers/action_mailer.rb
if Rails.env.development?
# Define settings for mailcatcher
Rails.application.config.action_mailer.tap do |action_mailer|
action_mailer.delivery_method = :smtp
action_mailer.perform_deliveries = true
action_mailer.raise_delivery_errors = false
action_mailer.smtp_settings = {address: "localhost", port: 1025}
end
end
if Rails.env.production?
# Define settings for sendgrid
Rails.application.config.action_mailer.tap do |action_mailer|
action_mailer.delivery_method = :smtp
action_mailer.perform_deliveries = true
action_mailer.raise_delivery_errors = true
action_mailer.smtp_settings = {
address: 'smtp.sendgrid.net',
port: '587',
authentication: :plain,
user_name: ENV['SENDGRID_USERNAME'],
password: ENV['SENDGRID_PASSWORD'],
domain: 'example.com',
enable_starttls_auto: true
}
end
end
Desta maneira, você pode simplesmente atualizar estes arquivos (config/application.rb
e config/environments/*.rb
), sem ter que se preocupar em olhar as diferenças entre as suas configurações e o que foi gerado pelo Rails.
Para facilitar um pouco esse processo, eu criei uma gem que diminui um pouco o atrito, já que você pode simplesmente copiar o código destes arquivos para os initializers, sem ter que fazer nenhuma mudança. Com esta gem, a mesma configuração poderia ser feita assim:
# config/initializers/action_mailer.rb
Rails.env.on(:development) do |config|
# Define settings for mailcatcher
config.action_mailer.delivery_method = :smtp
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = false
config.action_mailer.smtp_settings = {address: "localhost", port: 1025}
end
Rails.env.on(:production) do |config|
# Define settings for sendgrid
config.action_mailer.delivery_method = :smtp
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = true
config.action_mailer.smtp_settings = {
address: 'smtp.sendgrid.net',
port: '587',
authentication: :plain,
user_name: ENV['SENDGRID_USERNAME'],
password: ENV['SENDGRID_PASSWORD'],
domain: 'example.com',
enable_starttls_auto: true
}
end
Como saber o que mudou
A melhor maneira de saber o que mudou entre uma versão e outra é ler o guia de atualização do Rails Guides. Lá você verá informações mais relevantes sobre o que você deve adicionar, remover ou atualizar, com links para os commits que introduzem estas modificações.
Outra fonte muito importante é o blog oficial, que sempre publica artigos com as informações mais relevantes sobre aquela versão, com muitos links para changelogs.
Versão do Ruby
O Rails também exige certas versões do Ruby; geralmente a última versão estável do Ruby é a que tem mais preferência.
- Rails 3 ou superior exigem o Ruby 1.8.7, que foi terminado em 31 de julho de 2014.
- Rails 4 recomenda o uso de Ruby 2.0 e exige a versão 1.9.3 ou superior (a versão 1.9.3 será terminada em 23 de fevereiro de 2015).
- Rails 5 exigirá o Ruby 2.2.
Se você pretende utilizar uma versão do Ruby que tem atualizações com correções de bugs e segurança, precisará usar pelo menos Ruby 2.0. E isso precisa ser feito em pouco mais de um mês.
Dependências
Um outro problema muito comum na atualização da versão do Rails são dependências que param de funcionar. Eu costumo dizer que “dependência” tem esse nome e não é por acaso. Se o projeto for abandonado, você estará atrelado a um código que pode nunca mais ter atualizações (que podem incluir correções de bugs e segurança).
Por isso, evite utilizar gems para toda e qualquer funcionalidade (e, por favor, fuja de artigos do tipo “Gems que você sempre deve adicionar em todos os projetos”). Isso não significa que você deva criar código para tudo. Apenas saiba que se for algo trivial de ser feito, não faz muito sentido usar uma dependência externa para fazer isso.
Frequência das atualizações
Veja a data de lançamento das últimas versões do Rails:
- 4.2.0 - 20 de dezembro de 2014
- 4.1.0 - 8 de abril de 2014
- 4.0.0 - 25 de junho de 2013
- 3.2.0 - 20 de janeiro de 2012
- 3.1.0 - 31 de agosto de 2011
- 3.0.0 - 29 de agosto de 2010
Como você pode ver, o tempo entre o lançamento de uma versão e outra é relativamente alto, ao contrário do que muita gente gosta de dizer. Por isso, prepare-se e adicione ao seu ciclo de desenvolvimento tempo para fazer esta migração.
Lembre-se que o Rails tem uma política de manutenção bem definida.
- Correções de erros são feitas apenas na última versão (a menos que alguém do Core Team decida abraçar uma versão antiga, como o Rafael França fez com o Rails 4.1.x).
- Falhas de segurança são aplicadas nas duas últimas versões.
- Falhas de segurança severas são aplicadas conforme decisão do Core Team, que pode incluir ou não versões mais antigas.
É importante atualizar o seu projeto. Além de poder contar com novas funcionalidades e correções de bugs, você garante que seu projeto não esteja suscetível a falhas de segurança do framework.
Se você decidir usar uma versão que não é mais suportada pelo Core Team, terá a responsabilidade de corrigir bugs e falhas de segurança do framework, fazendo backport de versões mais recentes. Acredite, não é uma tarefa simples e, por isso, ninguém o faz.
Rodando o seu projeto
Chegou a hora mais temida: rodar o seu projeto para saber o que quebrou! Não preciso nem dizer que testes são importantes e irão ajudá-lo nesse processo de atualização. Se o seu projeto tem uma suíte de testes, execute-a e corrija as falhas até que todos os testes passem.
É muito importante que você leia as mensagens de erro. Caso a mensagem de erro não seja clara o suficiente, não seja preguiçoso: faça uma busca no Google. É muito provável que outras pessoas já tenham tido o mesmo erro e, possivelmente, você terá uma solução documentada.
Se você não tem testes, não tem muito o que você possa fazer. Navegue pelo site, realize os fluxos mais comuns e corrija os erros conforme eles forem aparecendo. Uma coisa que você pode fazer nesta etapa é automatizar esse processo de navegação com Capybara. Assim você já terá alguma cobertura de testes que pode ser utilizada futuramente no processo de desenvolvimento e irá ajudá-lo em uma nova atualização do Rails.
Finalizando
Antes de atualizar o seu projeto, você precisa analisar as motivações:
- Você precisa de alguma nova funcionalidade?
- Esta se tornando um fardo manter o código antigo ou encontrar bibliotecas que suportem a versão que você está usando?
- Você tem o tempo disponível para fazer esta atualização?
- Você precisa de alguma correção de bug que está disponível nesta nova versão?
Existem muitas outras perguntas que você pode se fazer. De um modo geral, você deve dedicar tempo do projeto para fazer esta atualização. Ficar preso a um código que não é mais mantido é um risco que eu prefiro evitar. E você?