Migrando uma aplica̤̣o do Rails 1.2.6 para Rails 2.3.2 РRiopro Blog
Migrando uma aplicação do Rails 1.2.6 para Rails 2.3.2
18 de Maio de 2009 otavio Deixe um comentário
Inspirado por este post do Peter Marklund resolvi documentar um upgrade recente de uma aplicação que rodava Rails 1.2.6 para Rails 2.3.2. O artigo também percorre alguns bugs encontrados e como foram resolvidos.
Bom, daqui para baixo, nem preciso avisar que seu código fonte deve estar em um controlador de versões como o Git (ou preciso?). E, de preferência, você estará em um branch estalando de novo para evitar as grandes besteiras.
Uma das idéias do Marklund, que também foi sugestão do Rodrigo, que acabamos seguindo foi a de começar a migração criando uma nova aplicação em Rails 2.3.2 zerada.
$ rails apptest
Isso facilita principalmente a parte das configurações básicas. Diretórios como config/initializers e config/locales não seriam criados sem isso, e initializers padrões como new_rails_defaults.rb também não. Por isso fizemos da raiz da aplicação que queremos atualizar:
$ mv config config_old
$ cp -R ../apptest/config ./
Só aí entramos no config_old/environment.br e passamos a pegar as configurações da aplicação antiga para a nova versão. O desejável é que você já vá separando as configurações específicas da aplicação em initializers próprios. Por exemplo, usamos um initializer/session_store.rb para configurar a ActionController::Base.session e a ActionController::Base.session_store. Ou seja, nada que você já não faça nas novas aplicações usando Rails >= 2.
Outra coisa importante é que, de cara apagamos todas as gems e alguns plugins vendorizados e fomos recolocando, já escrevendo o config.gem de cada uma no environment para podermos atualizar com versões que seguramente estavam mais atualizadas e compatíveis com o Rails 2.3.2.
Depois da atualização das gems e plugins estarem ok, foi a vez de começar o upgrade da aplicação. Passos obrigatórios foram:
O último é apenas para quem usa RSpec. Várias coisas mudaram no RSpec, um deles é que os testes para rotas passam a ter que ser comparados com o método (post, put, delete) esperado para a renderização da mesma (mas aí já estou entrando em detalhas demais).
Em seguida, fizemos o upgrade do nome das views. Para isso, usamos o script do post do Peter Marklund, muito bom para renomear arquivos .rhml em .html.erb e por aí vai. Vou postar abaixo o script, que pode ser salvo diretamente em um arquivo renomeando_views.rb e dado direito de execução:
# Extraído de: http://marklunds.com/articles/one/409
# change-extension
puts "Usage: #{$0}: "
MOVE_COMMAND = "git mv"
Dir[File.join(root_path, "**", "*.#{from_ext}")].each do |from_path|
command = "#{MOVE_COMMAND} #{from_path} #{to_path}"
O maior problema durante a migração ocorreu com o ARMailer. Apesar de termos atualizado o ARMailer para a última versão disponível (1.3.2), um erro nil.include? com no método create_time_zone_conversion_attribute. O erro era descrito assim:
You have a nil object when you didn't expect it!You might have expected an instance of Array.The error occurred while evaluating nil.include?
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/attribute_methods.rb:142:in `create_time_zone_conversion_attribute?'/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/attribute_methods.rb:75:in `define_attribute_methods'/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/attribute_methods.rb:71:in `each'
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/attribute_methods.rb:351:in `respond_to?'
Uma coisa interessante é que ele nunca ocorria na primeira vez. Mas ele sempre ocorria da segunda vez em diante. Ou seja, nada de testes quebrando, apenas se você testava e mais de uma vez. Depois de muito procurar, acabamos encontrando referências para a solução aqui, aqui e, finalmente, aqui. O último link descreve perfeitamente o nosso problema. A solução, até agora, é trocar no environment de development config.cache_classes de false para true. Isso é péssimo, serve só para testar e ver que nem tudo está "explodindo". Mas acho que o que vamos fazer mesmo é parar e usar o ARMailer e passar para jobs, como tem sido feito em aplicações nossas mais recentes como o Zest e o Zist.
Outro problema imbecil é que tínhamos um campo chamado hash para um determinado modelo e esse campo passou a ser um atributo reservado do ActiveRecord no Rails 2 em diante, lançando um erro de ActiveRecord::DangerousAttributeError. Nada demais, mas a mensagem de erro é mau relacionada ao motivo. Ela lança como se outro campo normal, por exemplo, name tivesse um erro de hash.
Outro passo dado (que não eram necessários mas deixa mais up-to-date a aplicação) foi colocar a configuração de internacionalização na aplicação.
De resto, até que não foi tão doloroso, apesar da aplicação ser grandinha. Já está tudo no ar e os Deuses da Performance agradecem.