Railsのアップグレード作業は検証含めて非常に面倒なもので、結構遅れがちなのですが、どこかで気合い入れてやらなければなーと思い、エイヤッとやってやりました。Rails3からやってるプロジェクトなので負債もまだまだ多いですが、とりあえずメジャーバージョンアップさえしておけば、他の技術も徐々に対応できるはず…。今回のアップグレードは5.2系から6.0系へのアップグレードです。
今回のアップグレードでやったこと
トレンドに追従できていないのは全然わかっていますが、頑張って追いかけるためにやれることはやっていきます😀
- Sprocketsを3から4に変更した
- sass-railsを6に変更した
- therubyracerをmini_racerに変更した
- Rails6をインストールして
bin/rails app:update
で差分を反映した - belongs_toに
optional: true
を付けていった - app/views/以下にある
*.js.coffee
のファイルを*.js.erb
に変更してCoffeeScriptからJavaScriptに修正した - Rails6からのローダーであるzeitwerkに対応するため、
bin/rails zeitwerk:check
を行い、クラス名を修正したり等を行なった ActionDispatch::HostAuthorization
を有効にするためにconfig.hostsに設定を行なった- credentials機能をバックポートしていたので、それを削除した
個別に解説するのもあれなので、ざっくりと書いていきます。
Sprocketsを3から4に変更した
まず雑にRails6系にしてbundle update rails
をしたら、色々と怒られまして、その中に入っていたと思います。これはSprockets3系に依存していたgemがあったためでした。たしか、css_spritter
だったかなと思います。これはIE9が1ファイルに付き4096までしかセレクタ定義を認識できないため、それ以上の定義を使おうと思ったらファイル分割するしかない、というやつですね。
これは昔、私がqiitaに記事を書いてます。
もうIE9のサポートは打ち切ったので、これを削除し、Sprocketsのバージョンを4系にしました。 この辺りでsass-railsを6にするのもなんか時間かかった気がしますが、何が原因だったか忘れました。
therubyracerをmini_racerにした
mini_racerの存在に気づいたのがつい最近というレベルで知らなかったのですが、以下の記事は3年前の記事です。これといってtherubyracerに依存しているようなものはないだろう、と思って変更しました。テストも通っているので大丈夫でしょう。
belongs_toにoptional: trueを付けていった
これはもう以前のバージョンの時点でやっておくべきだったことですが、放置していたので対応しました。belongs_toをつけると関連先がデフォルトで必須になる件です。config.load_modules 6.0
に設定して、頑張って直しました。
views以下のjs.coffeeをjs.erbに修正した
これは、assets以下のほうはjs.coffeeで動くのですが、views以下のほうがjs.coffeeを認識しなくなっていました。Ajaxでアクセスされた際に返すViewが以前は自動的にjs.coffeeになっていたのだけれど、ファイルの存在を認識してくれないからhtml側のViewを返してしまってエラーになっていました。
このままで動く方法を探そうとしたのですが、いまいちわからず…。Railsがcoffeeをサポートしなくなったからなんでしょうか?直し方がわからなかったので、拡張子のjs.coffeeをjs.erbに変換して、ファイルの内容もCoffeeScriptからJavaScriptに直したら、普通にAjaxで認識してくれるようになりました。
Ajaxで返す際のCoffeeScriptでは、大したことをしていなかったのでJSへの修正も簡単、かつファイル数も少なかったため、手動で直して終わり、としました。
zeitwerk対応
bin/rails zeitwerk:check
を行い、クラス名の修正等を行ないました。
zeitwerkはフォルダ構造とファイル名からnamespaceやクラス名を推測してロードを試みるため、多少の修正が必要でしたが、先ほどのコマンドで「こう直してほしい」と言われるので、大したことはありませんでした。一斉置換で対応可能でした。
ActionDispatch::HostAuthorization対応
これは、DNSリバインディング攻撃から保護するために追加されたミドルウェアの設定です。
config/application.rbやconfig/environments/production.rbなどで設定しておくと、設定されたドメイン以外でのアクセスを受けたらエラーになってくれます。
いろんなサブドメインで検証することもあるので、config/application.rbで以下のようにしました。(example.comはプロダクトのドメインに置き換えてください)
.example.com
とすることで、サブドメインをワイルドカードにすることができます。
config.hosts.push 'example.com', '.example.com'
設定はこれでいいのですが、インテグレーションテストを実行すると、この設定が仇となってエラーになります。
そこで、config/environments/test.rbの最後で、クリアしておきます。
config.hosts.clear
これで、テストも無事実行されるようになりました。
credentials機能をバックポートしていたので、それを削除した
これは以前に記事にした通り、Rails6系のcredentialsの機能を5.2にバックポートしていたのですが、正式に6系にしたため、不要になりましたので、削除しました。
削除した後に動作検証をして、問題ないことを確認しました。
これからやりたいこと
あくまでも私見ですが…
- CoffeeScriptをやめる
- Sprockets4からWebpackerに移行する
- bootstrap3から4に移行する
- knockout.jsからstimulusに移行する
- turbolinksを導入する
周回遅れ感がありますが、保守をしつつ、機能追加をしつつ、アップグレードしていくのは大変なのです😢若者がプロジェクトに入ってくれることになっているのですが、若者に今更CoffeeScriptとかやってもらうのは厳しいと思うので、本格的にアサインする前にこれらの一部でも倒しておきたい所存…。やっていくしかない。