一個rails2.3+ruby1.8項目升級到rails3.2+ruby1.9的記錄
經(jīng)過2個星期的折騰,終于將一個項目從rails2.3+ruby1.8升級到rails3.2+ruby1.9,記錄一下過程和踩到的地雷:
升級流程:
1. 在ruby1.8和rails2.3的環(huán)境下,在項目下安裝rails_upgrade插件: https://github.com/rails/rails_upgrade 運行下列命令,將輸出的內(nèi)容保存供后續(xù)使用。
A. rake rails:upgrade:check, 它會查找不兼容的語法和插件
B. rake rails:upgrade:routes, 會把rails2.3格式的route文件轉(zhuǎn)化成rails3格式
C. rake rails:upgrade:gems, 會把寫在environment.rb里面的gem管理方式變成bundle管理的Gemfile格式
D. rake rails:upgrade:configuration, 會將原先在environment.rb里面的其他設(shè)置轉(zhuǎn)化成rails3格式的config/application.rb文件
2. 用rvm切換到ruby 1.9.3, gem install rails v=3.2
A. 執(zhí)行rails new old_app_path 會提醒你是否要覆蓋一些文件(比如routes.rb等),可以選擇全部覆蓋(做好備份)
B. 將1.B生成的內(nèi)容,覆蓋到routes.rb
C. 將1.C生成的內(nèi)容,覆蓋到Gemfile
D. 將1.D生成的內(nèi)容,覆蓋到application.rb
E. 執(zhí)行bundle install,安裝必要的gem
3. 根據(jù)1.A的結(jié)果,升級插件和改必要的語法,如下幾個基本上都是可以全局查找替換的:
A. 插件升級,rails2的大部分插件到了3以后基本上就不能用了,比如searchlogic,可用meta_search來替代,比如cache-money,可用record-cache替代
B. 支持block的helper改變,比如form_for等支持block的helper,現(xiàn)在必須多個等號,改成‘<%= form_for’才能輸出html
C. RAILS_ROOT, RAILS_ENV等常量寫法,被Rails.root, Rails.env等模塊方法取代 ( http://quaran.to/blog/2010/02/03/the-rails-module/ )
D. named_scope 改成了 scope ( https://github.com/rails/rails/c ... a69041a4ddc2e0cc914 )
E. 郵件發(fā)送api改變 ( http://lindsaar.net/2010/1/26/new-actionmailer-api-in-rails-3 )
4. 下面是幾個比較折騰和change log里面不太注意的地方:
A. Rails 3默認使用了safebuffers: http://yehudakatz.com/2010/02/01/safebuffers-and-rails-3-0/這樣就可以不需要到處加<%= h ... %>,非常安全也非常方便,但是rails 2的項目中很多view和helper都需要改寫,一些不需要escape的代碼還要特別注意加上html_safe (比如richeditor的輸出結(jié)果)
B. ActiveRecord callback的語法改變,rails2我們可以在model里面寫
Ruby代碼- 1.class User
- 2. def after_save
- 3. self.xxx
- 4. end
- 5.end
- class User
- def after_save
- self.xxx
- end
- end
復(fù)制代碼 現(xiàn)在必須改成block方式:
Ruby代碼- 1.class User
- 2. before_save do |user|
- 3. user.xxx
- 4. end
- 5.end
- class User
- before_save do |user|
- user.xxx
- end
- end
復(fù)制代碼 C. rails_upgrade插件自動生成的routes.rb大部分能夠自動工作,但是還是有發(fā)現(xiàn)一些namespace的route,自動生成的會出錯,需要手工處理一下,改寫一下。
D. class_inheritable_accessor 方法改成了 class_attribute
E. request.request_uri 方法改成了 request.fullpath
F. rails3推薦無侵入式的JS,一些舊的onclick的helper都改寫成ujs方式
G. yaml的array格式改變(這個好像是ruby1.9的改變),原先可以寫
day_names: [星期一,星期二...]
現(xiàn)在改成了
day_names
- 星期一
- 星期二
H. ruby 1.9要求每個含有utf8字符的rb文件,必須在文件第一行有magic comment: # -*- encoding : utf-8 -*- 我覺的這個很折騰,為什么不是默認unicode呢?
5. 4里面的麻煩還算好,基本上耐心改寫,測試都可以搞定,這個項目升級遇到最大的麻煩是ruby 1.9 String encoding + yaml序列化的改變,1.8的String對象是不帶encoding屬性的,serialize一個屬性,如果有中文的話,會當作binary存入數(shù)據(jù)庫。
Ruby代碼- 1.class Product
- 2. serialize :properties, Hash
- 3.end
- class Product
- serialize :properties, Hash
- end
復(fù)制代碼 升級以后,必須用db migration,將數(shù)據(jù)庫里面所有的數(shù)據(jù)進行force_encoding,然后再保存:
Ruby代碼- 1.def up
- 2. rename_column :products, :properties, :old_properties
- 3. add_column :products, :properties, :text
- 4.
- 5. Product.reset_column_information
- 6.
- 7. Product.find(:all).each{|p|
- 8. if pro = p.old_properties
- 9. pro.each {|k, v|
- 10. pro[k] = v.force_encoding('UTF-8') if v.is_a? String
- 11. }
- 12. p.properties = pro
- 13. p.save!
- 14. end
- 15. }
- 16.end
- def up
- rename_column :products, :properties, :old_properties
- add_column :products, :properties, :text
-
- Product.reset_column_information
- Product.find(:all).each{|p|
- if pro = p.old_properties
- pro.each {|k, v|
- pro[k] = v.force_encoding('UTF-8') if v.is_a? String
- }
- p.properties = pro
- p.save!
- end
- }
- end
復(fù)制代碼 |