Go to English Blog

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:

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.

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:

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.

É 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:

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ê?