
最近、趣味で作っているサービス(Admiral Stats)を Rails 5.0.0.1 から 5.1.2 にアップグレードしました。サービスが小さいので、それほど苦戦するポイントは無かったのですが、調べたこと、やったことをメモしておきます。
調べたこと
とりあえず、関連しそうな情報に一通り目を通しました。
Rails のアップグレードの流れ
- Rails アップグレードガイド | Rails ガイド を読んで、全体の流れを確認
Rails 5.0 系内でのアップグレード内容
- rails/CHANGELOG.md at 5-0-stable · rails/rails を読んで、自分が使っている範囲では特に影響がないことを確認
Rails 5.0 → 5.1 のアップグレード内容
- Rails アップグレードガイドの “2. Rails 5.0からRails 5.1へのアップグレード” の節 を確認
- アップグレードガイドに書かれているのは「トップレベルのHashWithIndifferentAccessが弱く非推奨化された」と「application.secretsですべてのキーをシンボルとして読み込むようになった」の2点で、残りはリリースノートを読むようにとのこと
- Ruby on Rails 5.1リリースノート | Rails ガイド を確認
- リリースノートで強調されているのは以下の8点
- Yarnのサポート
- Webpackのサポート(オプション)
- デフォルトでのjQuery依存を廃止
- システムテスト
- 秘密情報の暗号化
- パラメータ化されたmailer
- directルーティングとresolvedルーティング
- form_forとform_tagのform_withへの統合
- しかし、個別の gem のリリースノートにも、Active Record の欄に「主キーのデフォルト型をBIGINTに変更」とか大きいのがあるので気を抜けない
Rails 5.1 系内でのアップグレード内容
すでに Rails 5.1 に移行した人の記事
- 特に参考にさせて頂いた記事はこのあたり
- 具体的な移行情報は参考になります。特に、僕はメドピア開発者ブログを読むまで、主キーが BIGINT に変わることを見逃してたので大変助かりました
アップグレード方針
上記のページを見る限り、今回は移行対象のアプリが小さいこともあり、特に問題もなくアップグレードできそうでした。
まず、「application.secretsですべてのキーをシンボルとして読み込むようになった」はコード中の参照箇所を確認して、問題なし。JWT のエンコード、デコード時に Rails.application.secrets.secret_key_base
と参照していましたが、これは Rails 5.1 でも動作しました。
秘密情報の暗号化は、元々 MySQL のパスワードなどは Apache から環境変数(SetEnv)で渡していたので、この方針を踏襲することにして変更せず。config/environments/production.rb で config.read_encrypted_secrets = false
と書いておいて、今まで通りに secrets.yml を使います。
Yarn のサポート、Webpack のサポート、デフォルトでのjQuery依存の廃止、については、引き続き jQuery を使うことにして今回は気にしないことに。
あと、主キーのデフォルト型が BIGINT に変更に変更される件については、テーブル作成時期によって主キーの型が変わるのは混乱しそうなので、INT に統一することにしました。アップグレード時に必要な作業は特にないですが、テーブル作成時に id: integer
を付ければ OK(以下はその例)。ただ、これはうっかり忘れることが多そうなので、generate model 時に必ず自動で付くようにしたい……。
class CreateBlueprintStatuses < ActiveRecord::Migration[5.1] def change create_table :blueprint_statuses, id: :integer do |t|
やったこと
Rails 5.0 系の最新版へのアップグレード、および関連 gem のアップグレード
まずは Gemfileのバージョンを更新。
- gem 'rails', '~> 5.0.0', '>= 5.0.0.1' + gem 'rails', '~> 5.0.0', '>= 5.0.4'
そして bundle update を実行。参考にしたページには bundle update rails を実行して rails 関係だけをアップグレードし、関連 gem は後回しにすべき、というアドバイスがあったのですが、すっかり忘れてました……。今回はそのまま続行。
最後に、動作確認のためにテストがある部分は rails test で確認し、ない部分は手作業で軽くポチポチ確認。
Rails 関係では特に問題ありませんでしたが、rack-cors が 0.4.1 から 1.0.0 に上がった影響で動作が少し変わっていて rails test が失敗。その部分のテストコードを修正しました。
あとは、Capistrano が 3.6.1 から 3.8.2 に変わった影響で、動かない部分と、Deprecation Notice が出る部分があったのでそこを修正。
- Capfile の修正
- lock '3.6.1' + lock '3.8.2'
- Capfile で Git SCM plugin のロードを明示
# Include default deployment tasks require "capistrano/deploy" # Future versions of Capistrano will not load the Git SCM plugin by default. + require "capistrano/scm/git" + install_plugin Capistrano::SCM::Git
Rails 5.1.2 へのアップグレード
先ほどと同じく、まずは Gemfile のバージョンを更新。
- gem 'rails', '~> 5.0.0', '>= 5.0.4' + gem 'rails', '~> 5.1.0', '>= 5.1.2'
次は bundle update を実行。関連 gem はアップグレード済みなので、今回は rails 関連の gem のみがアップグレードされました。
そして rails app:update
を実行。bin 以下と config 以下のファイルが、新規作成されたり上書きされたりします。git で差分を見て、既存の設定を上書きしている部分以外は、基本的に採用しました。
- bin/setup
- bin/yarn の読み込みがコメントアウトされた状態で追加された。参考のために残した
# Install JavaScript dependencies if using Yarn # system('bin/yarn')
- bin/yarn (新規作成)
- 今回は使わないが、呼び出し自体は上記の通りコメントアウトされているので残した
#!/usr/bin/env ruby VENDOR_PATH = File.expand_path('..', __dir__) Dir.chdir(VENDOR_PATH) do begin exec "yarnpkg #{ARGV.join(" ")}" rescue Errno::ENOENT $stderr.puts "Yarn executable was not detected in the system." $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install" exit 1 end end
- config/application.rb
- 以下の行が追加された。確認のうえで残した
+ config.load_defaults 5.1
- config/cable.yml
- Redis PubSub で使う prefix が追加された。設定しても、この自作サービス(Admiral Stats)では使わないが、自動生成されたまま残した
+ channel_prefix: admiral_stats_production
- config/puma.rb
- ビルトインサーバの設定。コメントが変わっただけ
- config/routes.rb
- 単純に空にされるだけなので、上書きされたものをもとに戻した
- config/secrets.yml
- 環境変数から読み込む運用にしているので、そのままにした
- config/environments/development.rb
- Cache-Control の表記が分かりやすい表記に変わった(max-age の長さは同じ)ため、そのまま残した
- 'Cache-Control' => 'public, max-age=172800' + 'Cache-Control' => "public, max-age=#{2.days.seconds.to_i}"
- config/environments/production.rb
config.read_encrypted_secrets = true
という行が追加されるが、これを false に変更した
- config/initializers/assets.rb
- 以下の行が追加された。Yarn は使っていないが、そのままにした
Rails.application.config.assets.paths << Rails.root.join('node_modules')
- config/initializers/cors.rb
- 基本的な設定が作成されたが、このファイルは元々作成済みだったため、元に戻した
- config/initializers/new_framework_defaults_5_1.rb
- 以下の内容で作成された。そのままにした。
# Be sure to restart your server when you modify this file. # # This file contains migration options to ease your Rails 5.1 upgrade. # # Once upgraded flip defaults one by one to migrate to the new default. # # Read the Guide for Upgrading Ruby on Rails for more info on each option. # Make `form_with` generate non-remote forms. Rails.application.config.action_view.form_with_generates_remote_forms = false # Unknown asset fallback will return the path passed in when the given # asset is not present in the asset pipeline. # Rails.application.config.assets.unknown_asset_fallback = false
最後に、動作確認のためにテストがある部分は rails test で確認し、ない部分は手作業で軽くポチポチ確認して、リリースしました。
まとめ
5.0 から 5.1 へのアップグレードは、それほど詰まるところはありませんでした。アップグレードが溜まってると辛くなるので、早いうちにやっておいてよかったです。
ただ、当たり前の話ですが、アップグレード前にはちゃんとテストを整備しておかないとダメですね。今回のアップグレード対象は趣味のサービスで、テストより機能追加を優先してしまっていたので、今回のアップグレードはおっかなびっくりでした。なにか僕の気付いていない問題が見つかったら、報告頂けたら緊急で対応します……。