Rails 3.0 -> Rails 3.1 アップデートメモ: Rails update (1)

はじめに

いまだに Rails 3.0 のシステムがあり、これをなんとかしたいと考えていました。新規に Rails 6.0 のシステムにコンバートしながら新機能を実装していたのですが、あまりに規模が大きくていつまで経っても終わらない気配なので、今のシステムを少しずつ上げてしまった方が早いのではと考え直しました。ほとんどの人にとっては役に立たない単なる個人的メモです。トラブったときに後で確認できるように記録しておきます。

Ubuntu 18.04 環境構築

当初、Vmware Fusion player に Ubuntu 20.04 を新規インストールしました。rbenv で Ruby 1.9.3 をインストールしようとしたところ、openssl の 1.0 系が入らないため、断念しました。取り急ぎ別途用意してあった、18.04 の Ubuntu を使うことにしました。こちらに rbenv をインストールし、Ruby 1.9.3-p551 をインストールしました。

なお、インストールしているのは Ubuntu Server なので、ウインドウは必要ありません。そこで、以前作成した ubuntu.sh でヘッドレス起動しています。

#!/bin/sh

VMRUN="vmrun -T fusion"
VM="$HOME/Virtual Machines.localized/Ubuntu (64 ビット) Server 18.04.2.vmwarevm/Ubuntu (64 ビット) Server 18.04.2.vmx"

case "$1" in
  "start" ) $VMRUN start "$VM" nogui ;;
  "stop" ) $VMRUN stop "$VM" ;;
  "suspend" ) nfs_umount.sh; $VMRUN suspend "$VM" ;;
  "stopsoft" ) nfs_umount.sh; $VMRUN stop "$VM" soft ;;
  "suspendsoft" ) nfs_umount.sh; $VMRUN suspend "$VM" soft ;;
  * ) echo "ubuntu.sh [start|stop|suspend|stopsoft|suspendsoft]" ;;
esac

このスクリプトにも書いてありますが、Ubuntu 側のディスクは macOS 側に nfs でマウントしています。今回、Rails アプリのフォルダも一緒に mount するようにしました。Ubuntu の IP は~/.ubuntu_ipに記載しています。VMware 12 に上げた時に IP が変わっていたのに気づかず、最初接続できなくて焦りました。

#!/bin/sh
sudo mount_nfs -P `cat $HOME/.ubuntu_ip`:/home/hkob $HOME/ubuntu
sudo mount_nfs -P `cat $HOME/.ubuntu_ip`:/opt/webcitc $HOME/rails/webcit2020

umount のスクリプトはこちらです。

#!/bin/sh
sudo umount `cat $HOME/.ubuntu_ip`:/home/hkob
sudo umount `cat $HOME/.ubuntu_ip`:/opt/webcitc

次に現状の Rails アプリを clone して、テストを動かしたところテストが一つだけ通過しませんでした。確認したところ、PostgreSQL の Encode が en_US.UTF-8 になっていたため、ソート順が合わなかったためでした。ja_JP.UTF-8 で PostgreSQL の initdb をやり直したところ、無事にテストが全部通過しました。

ZenTest -> Guard の移行

ZenTest は色々の環境構築が面倒なので、普段使っている Guard に移行しました。 Ruby が 1.9.3 なので、Gemfile は基本的に「<バージョン」として上限を指定しないと、インストールができません。

Rubygems v2.0系でないとインストールできないことに注意
- gem 'ZenTest', '4.9.2'

+#  gem 'ZenTest', '4.9.2'
- gem 'autotest-screen'

+#  gem 'autotest-screen'

+ gem 'lumberjack', '<1.0.13'
+ gem '<ffi', '1.11.0'
+ gem 'rb-inotify', '<0.10.0'
+ gem 'guard-rspec'

Rails 3.0 の頃は spring がなく、spork を使っていました。取り急ぎ、spork を単体で起動したのち、Guard でフルテストを実施したところ、こちらでも無事テストが全部通過しました。

rails 3.1.12 gem への変更

まず、Gemfile の Rails のバージョンを変更します。

gem 'rails', '3.1.12'

次に bundle update します。Ruby 1.9.3 が未対応になるものが多数あるので、「<バージョン」で上限を決めるか、使っていなそうなものは思い切って削除します。今回、cucumber (turnip) については、ほとんど意味のあるテストを書いていなかったので削除しました。また、現在の運用環境では passenger を使っていましたが、今回は puma + nginx に変更しようと思っています(passenger の runtime を作るのが面倒なためです)。

次に設定ファイルを更新します。単に rake rails:update とするとファイルの置き換えしかできないため、vimdiff を使ってマージをするとよいようです。

env THOR_DIFF=vimdiff rake rails:update

conflict したファイルがあった場合、「d」をタイプすることで、vimdiff が起動します。この時、左側に現在のファイル、右側に新しい Rails の設定ファイルが表示されます。左右で違う部分の色が変わって表示されるので、左側の新しい設定を右側の古いファイルに適用します(同じ表示になれば色が消えます)。これまで、空の新規アプリを作って、比較しながら編集していました。これは楽ですね。

最後に assets を移動します。

mkdir app/assets
mv public/images app/assets
mv public/javascripts app/assets/
mv public/stylesheets app/assets/

次のコマンドでサーバを動かしてみます。3000 番ポートにアクセスするといつもの画面が表示されました。

be rails server

テストの実行

そのまま rspec を実行したら大量のエラーが出ました。bundle update で RSpec もかなりバージョンが上がったためでした。以前は、spec_helper.rb だけに設定を記述していましたが、RSpec が Rails 以外にも使われるようになったことから、rails の設定が rails_helper に移動したためのようです。まず、rspec の初期化をやり直すことにします。rails:update と同様に rspec:install を vimdiff でマージしました。

env THOR_DIFF=vimdiff bundle exec rails g rspec:install

これまでの *_spec.rb の頭には require 'spec_helper' と書かれていたので、これを全て require 'rails_helper'に修正します。フォルダ内を一括置換した後で、rails_helper.rb の頭だけspec_helper に戻しました。また、3.0 の時代はテスト高速化のために、spork を使ってきました。しかし、spec_helper, rails_helper の記述法が怪しかったので、今回はバッサリ捨てました。どうせ後で spring に移行するためです。

また、stub! などの古い記述を全て直す必要がありました。double と allow などに直す必要があります。これはかなりかかります。手作業で直すのは大変なので、正規表現で変換したのち、エラーになるものだけ手作業で修正しています。mock() が一番多いのですが、ここはわざと手作業で修正しています。receive_message_chain を知らなかった頃に書いたテストで多用していたためです。この部分は手作業で receive_message_chain に変更していきました。

%s/\(  *\)\(.*\)\.stub_chain/\1allow(\2).to receive_message_chain/
%s/\(  *\)\(.*\)\.stub!/\1allow(\2).to receive/
%s/\(  *\)\(.*\)\.stub(/\1allow(\2).to receive(/
%s/\(  *\)\(.*\)\.should_receive/\1expect(\2).to receive/
%s/\(  *\)\(.*\)\.should ==/\1expect(\2).to eq/
%s/\(  *\)\(.*\)\.should /\1expect(\2).to /
%s/be_true$/be_truthy/
%s/be_false$/be_falsey/

あとは、DEPRECATION WARNING への対応をします。まず、最初は Sass 3.5 について、以下のメッセージが出ます。現在、Ruby 1.9.3 で動作するギリギリの Sass 3.4.25 まで上げたからでした。Rails 4.0 に上げた時に、Ruby 2.0 に上げる予定なので、それまで無視します。

DEPRECATION WARNING:
Sass 3.5 will no longer support Ruby 1.9.3.
Please upgrade to Ruby 2.0.0 or greater as soon as possible.

もう一つの WARNING が以下のものです。 config/routes.rb には devise しか書かれていません。ということで、それを踏まえて検索したところ、以下のディスカッションを見つけました。ここに「Are you using devise? I got rid of the same deprecation warnings by upgrading my devise version from 1.2.x to 1.3.4.」と書かれています。

DEPRECATION WARNING: ref is deprecated and will be removed from Rails 3.2.
DEPRECATION WARNING: new is deprecated and will be removed from Rails 3.2.
DEPRECATION WARNING: get is deprecated and will be removed from Rails 3.2.

devise は属性などの問題ではまりそうだったので、バージョン固定していましたが、やはり上げないといけないようです。devise_ldap_authenticatable が devise のバージョン指定をしているので、これも外してみたところ、0.4.6 → 0.7.0 となり、devise も 1.1.2 → 2.2.8 になりました。これでログインなどがそのままうまくいくか試してみます。

あと、忘れがちな PostgreSQL 10 対策も抜けていました( active_record/connection_adapters/postgresql_adapter のパッチ)。reset_pk_sequence! がエラーになるので、このパッチも手動で当てておきます。Rails 本体の修正ですが、Rails 自体のバージョンが上がれば対応されるものなので、ここではモンキーパッチで十分だと考えています。

これで、全てのテストを書き換えて rspec を実行してみました。とりあえず用意されているテストは全部通っています。結果はこんな感じ。カバレッジが低いけど仕方ないですかね。

Finished in 24 minutes 19 seconds (files took 1 minute 45.1 seconds to load)
7724 examples, 0 failures, 99 pending

Coverage report generated for RSpec to /opt/webcitc/coverage. 24777 / 35721 LOC (69.36%) covered.

なお、gem の差分はこんな感じになっています。

gem_name ver3.0 ver3.1 changed
ZenTest 4.9.2 -
abstract 1.0.0 -
actionmailer 3.0.20 3.1.12
actionpack 3.0.20 3.1.12
activemodel 3.0.20 3.1.12
activerecord 3.0.20 3.1.12
activeresource 3.0.20 3.1.12
activesupport 3.0.20 3.1.12
arel 2.0.10 2.2.3
autotest-screen 0.1.0.1 -
bcrypt 3.1.16 +
bcrypt-ruby 2.1.4 3.1.5
better_errors 1.1.0 1.1.0 =
binding_of_caller 0.7.2 0.8.0
brakeman 2.1.0 4.4.0
builder 2.1.2 3.0.4
bullet 4.3.0 -
capybara 2.2.1 -
choice 0.1.6 0.1.7
ci_reporter 1.8.4 2.0.0
cliver 0.3.2 -
coderay 1.1.0 1.1.3
coffee-rails 3.1.1 +
coffee-script 2.4.1 +
coffee-script-source 1.12.2 +
concurrent-ruby 1.1.7 +
cucumber 1.3.5 -
daemon_controller 1.1.5 -
daemons 1.0.10 -
database_cleaner 1.5.3 1.8.5
debug_inspector 0.0.2 0.0.3
devise 1.1.2 2.2.8
devise-encryptable 0.2.0 +
devise_ldap_authenticatable 0.4.6 0.7.0
diff-lcs 1.2.4 1.4.4
docile 1.3.2 +
dotenv 0.10.0 2.7.6
erubis 2.6.6 2.7.0
execjs 2.7.0 +
factory_bot 4.11.1 +
factory_bot_rails 4.11.1 +
factory_girl 4.3.0 -
factory_girl_rails 4.3.0 -
fastercsv 1.5.5 -
ffi 1.10.0 +
formatador 0.2.5 +
gem_plugin 0.2.3 -
gherkin 2.12.0 -
guard 1.8.3 +
guard-rspec 1.2.2 +
haml 3.1.8 4.0.7
haml-rails 0.3.4 0.4
highline 1.6.19 1.2.3
hpricot 0.8.6 0.8.6 =
i18n 0.5.0 0.9.5
interception 0.4 0.5
jquery-rails 3.0.4 3.1.5
json 1.8.0 1.8.6
kaminari 0.10.4 0.17.0
listen 1.3.1 +
lumberjack 1.0.12 +
mail 2.2.20 2.4.4
method_source 0.8.2 0.9.2
mime-types 1.23 1.25.1
mini_portile 0.5.1 -
mini_portile2 2.1.0 +
mongrel 1.2.0.pre2 -
multi_json 1.7.7 1.15.0
multi_test 0.0.2 -
net-ldap 0.1.1 0.3.1
nokogiri 1.6.0 1.6.8
orm_adapter 0.5.0 +
passenger 4.0.10 -
pg 0.16.0 0.18.4
pkg-config 1.1.9 +
poltergeist 1.5.0 -
polyglot 0.3.3 0.3.5
pry 0.9.12.6 0.12.2
pry-doc 0.5.1 0.10.0
pry-rails 0.3.2 0.3.9
pry-rescue 1.4.0 1.5.2
public_suffix 1.4.6 +
puma 3.11.4 +
rack 1.2.8 1.3.10
rack-cache 1.7.1 +
rack-mount 0.6.14 0.8.3
rack-ssl 1.3.4 +
rack-test 0.5.7 0.6.3
rails 3.0.20 3.1.12
rails-erd 1.1.0 1.1.0 =
railties 3.0.20 3.1.12
rake 0.8.7 12.2.1
rb-fsevent 0.10.4 +
rb-inotify 0.9.10 +
rb-kqueue 0.2.5 +
rb-readline 0.4.2 0.5.5
rdoc 3.12.2 3.12.2 =
redcarpet 3.3.3 3.5.0
rspec 2.13.0 -
rspec-core 2.13.1 3.9.3
rspec-expectations 2.13.0 3.9.4
rspec-mocks 2.13.1 3.9.1
rspec-rails 2.13.2 3.9.1
rspec-support 3.9.4 +
ruby-graphviz 1.0.9 1.0.9 =
ruby2ruby 2.0.6 -
ruby_parser 3.2.2 -
sass 3.2.10 3.4.25
sass-rails 3.1.7 +
sexp_processor 4.2.1 -
simplecov 0.7.1 0.17.1
simplecov-html 0.7.1 0.10.2
simplecov-rcov 0.2.3 0.2.3 =
slim 2.0.0 -
slop 3.4.7 -
spork 0.9.2 -
sprockets 2.0.5 +
temple 0.6.5 -
terminal-table 1.4.5 -
thor 0.14.6 0.14.6 =
tilt 1.4.1 1.3.7
treetop 1.4.14 1.4.15
turnip 1.2.1 -
tzinfo 0.3.37 0.3.58
uglifier 4.2.0 +
uniform_notifier 1.2.0 1.11.0
warden 0.10.7 1.2.7
watchr 0.7 0.7 =
webrat 0.7.3 -
websocket-driver 0.3.2 -
xpath 2.0.0 -
yard 0.8.7.3 0.9.25
yard-activerecord 0.0.15 0.0.16

とりあえず一段落したので、コミットしておきます。

hkob.hatenablog.com