Ruby Weekly #374: 日本語サマリー
職場の Slack の #ruby 窓で Ruby Weekly メルマガが毎週配信されます。その中から面白そうなものをピックアップして、日本語で簡単なサマリーを書くようにしています。そのサマリーをここでまとまさせていただきます。くだけた日本語で失礼いたします。
Highlights
下記理由で Sprockets から Webpack に移行した LearnZillion 社。
- Sprockets が重い。
- ES6 欲しさ(Sprockets にもあるが、未だに experimental)。
- Sprockets が提供してくれない機能欲しさ。
- Webpack が Rails Way となった。
移行計画
- 準備フェーズ
- Webpacker 追加
- 環境構築
- Nginx、capistrano 設定
- デプロイ
- 移行フェーズ
- Rails asset 用 gem を NPM パッケージで置換
- アピリコードを Webpack に移行
- 必要に応じて Webpack 設定修正
- クリーンアップフェーズ
- Rails asset 用 gem 削除
- Sprockets 設定削除
- Webpack バンドル最適化
問題点
- JavaScript 単体テストの二重メンテ
- 依存していたグローバル変数の維持が大変(ライブラリなど)
- Sprockets バンドルから Webpack バンドルに移行するのが安易ではなかった
コード豊富なので原文参照。
9 年ものレガシー Rails アプリを Rails 5 にバージョンアップした Kickstarter 社。
- 段階的アップグレード
- リリースノートに従った修正
- gem を v5 にアップグレード
- Rails 5 専用ブランチで
- 依存問題で落ちる他 gem をまず修正(Ready4Rails 超便利)
- Rails アップグレードスクリプト実行
- Rails 4.2 にマージできる修正を master ブランチにマージ
- Rails 5 専用ブランチを CI グリーンに
- Rails 5 専用ブランチの deprecation 忠告撲滅
- Rails 5 専用ブランチを手動で動かす
- テストでカバーできてない問題特定のため
- master ブランチで今までの修正をバックポート
- 各機能の開発チームに自分の機能をテストしてもらう
- staging 環境にデプロイ
- 本番デプロイ
- カスタマーサポートからのバグチケ消化
- 振り返り
結果
- 見積もりどおりの 3 ヶ月で完了
- 大規模ダウンタイムなし
- カスタマーサポートのバグチケ対応計画たてとけばよかった
- いろいろ学習できた
- 影響範囲の最も広かった変更点は
HashWithIndifferentAccess
を継承しなくなったActionController::Parameters
。Hash
を継承していることを前提にしたコードがいっぱいあったから。 - モバイルアプリへの影響は少なかったが、予想しなかった。ネイティヴチームのエンジニア巻き込んどけばよかった。
API の重いリクエストで悩まされた Kollegorna 社は、フレイムグラフ見てもネックが特定できなかった。そこでクラス単位でメソッドをベンチマークしてくれる ClassProfiler gem を作ることに。%の最も高いメソッドの中で呼ばれるクラスを次々とベンチマークすることで、やっと犯人に辿り着いた。
先週サービスオブジェクトの使いすぎを否定した Avdi Grimm 先生への反論。
- モジュールメソッドだとどんどん増えていき、結局 junk drawer になる。
- 筆者の経験では、サービスオブジェクトが統一したコードへと繋がった。
- サービスオブジェクトを支える ActiveInteraction gem まで作った。
Rails アプリの多数データベース用 gem。
News
Semaphore CI ユーザが採用している Ruby バージョン別分布。
JRuby 9.1.14.0 リリース。
RubyGems 2.7.2 リリース。
bundle gem
コマンドで新規 gem 生成できなくなっていたバグ解消。- git がインストールされていない環境でエラっていたバグ解消。
Tutorial
インタラクターデザパタ用 interactor gem の紹介。
- Fat Controller の各工程をそれぞれサービスオブジェクトに抽出して、
Interactor
モジュールをinclude
。 Interactor::Organizer
をinclude
したオブジェクトでサービスオブジェクトの呼び出し順番を定義。Interactor
が提供してくれるbefore
around
after
フックでトランザクションを張ったりする。- gem は非常に計量(ソースが小さい)。
Interactor::Organizer
に並べたサービスオブジェクトは Context オブジェクトを共有するのがちょっとグローバル変数っぽくて要注意。- gem は validation 仕組みを提供してくれないので、筆者が validation 用
Interactor
を提案した。
$LOAD_PATH
に載っていないのに gem を require
できるようにしてくれる RubyGems コードリーディング。Kernel#require
のモンキーパッチで、LoadError
発生時の rescue
ブロックで、インストール済み gem の中から探す。見つけた場合、$LOAD_PATH
に追加し、require
再挑戦。
Rack::Deflate
ミドルウェアで Rails レスポンスを gzip 圧縮してサイズを 80% 減らした Richard Schneeman 先生。
&.
演算子の罠。<
などの評価順番が変わっちゃうから要注意。(原文コード参照)
数百万行もの PostgreSQL テーブルをパーティション分割した Evil Martians 社。
- 親テーブルをクローン。
- 子テーブル + 親テーブルの PK をマッピングするビュー作成。
- 子テーブルを作成・更新するストアドプロシージャ作成。
- ストアドプロシージャを呼ぶトリガーをビューに張る。
- ActiveRecord モデルがビューを見るように設定。
- 既存データはビューに
INSERT
することで移行。
Array#transpose
いろいろ。
- 二次元配列で行と列を入れ替えてくれる。
- 三目並べゲームの勝利判定ロジックを例に挙げた。
Rails 3.2 アプリを 4.0 にアップグレードするための豆知識。移行してない人がまだまだいるから。
- Ruby 1.8.7 を使っていれば、1.9.3 にアップグレード。
- rails4_upgrade gem を Gemfile に追加して、アップグレードの必要な gem を特定。
rails:update
Rake タスクで不要な設定・モンキーパッチを削除。- RailsDiff で予想された差分を確認。
- activerecord-deprecated_finders gem で
.find_by_hoge
メソッドを洗い出し・撲滅。 - scope は全部 lambda 表記に。
protected_attributes
撲滅。あるいは protected_attributes gem 導入。Strong Parameters に移行することがベスト。ActiveRecord::Observer
撲滅。あるいは rails-observers gem 導入。wisper gem または Rails Concerns に移行するのがベスト。ActiveResource
は active_resource gem に移行。caches_page
caches_action
は actionpack-action_caching gem に移行。Test::Unit
は test-unit gem に移行。match
式 route は HTTP メソッド要指定。- プラグインを使っていれば gem に移行。
Code
Alpha Vantage API を叩く両替 gem。Alpha Vantage 以外でも拡張可能。キャッシュ期限設定可能。他 gem への依存が一切ない。
ActionCable など WebSocket サーバテスト用 CLI ツール gem。データ送受信スクリプトを YAML で定義してから wsdirector
コマンドで実行。ApplicationCable::Channel
の単体テストと思えば良さそう。(RSpec・MiniTest・Test::Unit とは別物)