Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Railsバージョンを4倍にした話

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers. →
Avatar for OPTiM OPTiM
October 16, 2026

 Railsバージョンを4倍にした話

2026/10/16 開催「Kaigi on Rails 2026」でのオプティム skytomo​ の発表資料です。

Avatar for OPTiM

OPTiM

October 16, 2026

More Decks by OPTiM

Other Decks in Programming

Transcript

  1. Railsのバージョンアップに成功! R ai l s U p g r ad

    e S uc c es sf ul ! 2 8 Ruby 1 3 Rails © 2019-2026 OPTiM Corp. All rights reserved. 5
  2. どうしてこんなになるまで放っておいたんですか? Why did you let it get this bad? 経緯はよくわからない

    I'm not entirely sure of the circumstances 真に忘れられたプロダクトは経緯も忘れられる For products that are truly forgotten, the story behind them is forgotten as well. おそらくはこう? • • 開発チームは途中で解散して引き継ぎがなくなった 運用チームはずっといた • 比較的小さいプロダクトの小さいサーバーアプリだったため、手を入れられることがなかった? • 手をいれずに、すべて運用回避 © 2019-2026 OPTiM Corp. All rights reserved. 9
  3. Rails Update (imagine) 2 3 4 5 6 7 8

    © 2019-2026 OPTiM Corp. All rights reserved. 12
  4. Rails Update (actually) 2 3 4 5 6 78 ©

    2019-2026 OPTiM Corp. All rights reserved. 13
  5. Rails Update (actually) 2 Routing DSL Bundler Active Record query

    script/* → rails …… 3 4 5 6 78 Strong Parameters classic autoloader → ActiveRecord::Base Turbo → ApplicationRecord update_attributes → *_filter → *_action © 2019-2026 OPTiM Corp. All rights reserved. 14
  6. Rails Update (actually) 2 Routing DSL Bundler Active Record query

    script/* → rails …… 3 4 5 6 78 Strong Parameters classic autoloader → ActiveRecord::Base Turbo → ApplicationRecord update_attributes → *_filter → *_action © 2019-2026 OPTiM Corp. All rights reserved. 15
  7. Rails Update (actually) 2 3 4 5 6 78 Strong

    Parameters classic autoloader → Rails Routing DSL バージョンアップの壁を超えられなかった Bundler Gemがたくさんある……! Turbo ActiveRecord::Base Active Record querygems couldn’t survive the Rails upgrade...! So many → ApplicationRecord update_attributes → script/* → rails *_filter → *_action …… © 2019-2026 OPTiM Corp. All rights reserved. 16
  8. Gemの移行例 わりとスムーズに移行できる Gems that migrated fairly smoothly ◼mysql → mysql2

    ◼factory_girl → factory_bot_rails ◼ruby-debug → debug ちょっとスムーズに移行できる Gems that migrated somewhat smoothly ◼restful_authentication → devise 移行するのが難しかった Gems that were difficult to migrate ◼2dc_jqgrid → 自前のjqgrid © 2019-2026 OPTiM Corp. All rights reserved. 17
  9. Gemの移行例 わりとスムーズに移行できる Fairly Smooth Gems that migrated fairly smoothly ◼mysql

    → mysql2 ◼factory_girl → factory_bot_rails ◼ruby-debug → debug 正式の後継Gemが存在する An official successor gem exists ちょっとスムーズに移行できる Somewhat Smooth Gems that migrated somewhat smoothly ◼restful_authentication → devise 移行するのが難しかった 豊富な移行手順が存在する Gems that were difficult to migrate Detailed migration guides are available ◼2dc_jqgrid → 自前のjqgrid © 2019-2026 OPTiM Corp. All rights reserved. 18
  10. Gemの移行例 わりとスムーズに移行できる Difficult Gems that migrated fairly smoothly ◼mysql →

    mysql2 ◼factory_girl → factory_bot_rails ◼ruby-debug → debug ちょっとスムーズに移行できる Gems that migrated somewhat smoothly ◼restful_authentication → devise 移行するのが難しかった 元のリポジトリが行方不明 The original repository is missing 古のjQuery 1.3.2(今は3.7.1) Ancient jQuery 1.3.2 (now 3.7.1) 後継は有償ライセンス The successor is under a paid license →自前のGemとして管理 Gems that were difficult to migrate Maintain it as our own gem ◼2dc_jqgrid → 自前のjqgrid © 2019-2026 OPTiM Corp. All rights reserved. 19
  11. 今回覚えて帰ってほしいキーワード Key Takeaways from Today 古い設定より古い規約 Old Convention over Old

    Configuration 設定はコードを見ればわかる 規約は調査しないとわからない Configuration can be understood by reading the code. Conventions require investigation to understand. © 2019-2026 OPTiM Corp. All rights reserved. 24
  12. 今回覚えて帰ってほしいキーワード Key Takeaways from Today 古い設定より古い規約 Old Convention over Old

    Configuration コード修正より調査 Investigation over Code fix © 2019-2026 OPTiM Corp. All rights reserved. 25
  13. コード修正よりも調査が重要 調査すれば自ずとどこをコード修正すべきかわかる Investigation is more important than modifying the code.

    Once you investigate, the necessary code changes will naturally become clear. © 2019-2026 OPTiM Corp. All rights reserved.
  14. コード修正の前に調査で行うこと What to Investigate Before Changing the Code ドキュメントを探そう Find

    the documentation ブランチを探そう Find the relevant branch ローカルで動かそう Get it running locally テストを走らせよう Run the tests 一気に上げるか少しずつ上げるか Decide whether to upgrade all at once or incrementally © 2019-2026 OPTiM Corp. All rights reserved. 27
  15. 最初に探すもの What to Look for First 商品サイト リポジトリ Product Site

    Repository チケット管理 ドキュメント Ticket System Documentation © 2019-2026 OPTiM Corp. All rights reserved. 29
  16. 最初に探すもの What to Look for First 商品サイト リポジトリ Product Site

    Repository チケット管理 ドキュメント Ticket System Documentation © 2019-2026 OPTiM Corp. All rights reserved. 30
  17. 商品サイトを探す Find the Product Website 背景を把握する Understand the background. 外部向けに、何ができる製品として紹介されているかを知る

    Learn how the product is presented to external audiences. その機能一覧が、守るべき挙動とテスト観点の足がかりになる The feature list is a starting point for what behavior to preserve and what to test. ドメイン知識が全くない場合に有効 Especially useful when you have no domain knowledge. © 2019-2026 OPTiM Corp. All rights reserved. 31
  18. 最初に探すもの What to Look for First 商品サイト リポジトリ Product Site

    Repository チケット管理 ドキュメント Ticket System Documentation © 2019-2026 OPTiM Corp. All rights reserved. 32
  19. リポジトリを探す Find the Repository SVNリポジトリはGitリポジトリに移行する Migrate the SVN repository to

    Git. ◼移行にはgit svn コマンドを使用する Use the git svn command for the migration. © 2019-2026 OPTiM Corp. All rights reserved. 33
  20. Git for Windows 2.54.0 以降 git svn コマンドのサポートは終了しました Git for

    Windows stopped bundling git svn in 2.54.0. Upstream Git still includes it. © 2019-2026 OPTiM Corp. All rights reserved.
  21. 移行したいけどできていない方はこのスライドのスクリーンショットを撮って上司に送ろう! If you want to make the switch but haven't

    yet, take a screenshot of this slide and send it to your boss! git svn ンドのサポートが終了 コマ ? ! れ Gitに移行できていないならもう 手遅 ギリ でも今ならまだ ギリ 間に合う! If you haven't migrated to Git, you are already too But there's still just enough time to make it! Migrate now © 2019-2026 OPTiM Corp. All rights reserved. 36
  22. 最初に探すもの What to Look for First 商品サイト リポジトリ Product Site

    Repository チケット管理 ドキュメント Ticket System Documentation © 2019-2026 OPTiM Corp. All rights reserved. 37
  23. チケット管理システムを探す Find the Ticket Management System 開きっぱなしのチケットがないか確認する Check for any

    open tickets. 閲覧権限を確認する Verify that you have access. ◼必要な情報があるのに、権限が足りなくて見えていないことがあった There were cases where the required information existed, but it was not visible due to insufficient permissions. © 2019-2026 OPTiM Corp. All rights reserved. 38
  24. 最初に探すもの What to Look for First 商品サイト リポジトリ Product Site

    Repository チケット管理 ドキュメント Ticket System Documentation © 2019-2026 OPTiM Corp. All rights reserved. 39
  25. ドキュメントを探す Find the Documentation 設計書を探す Find the Design Documents 外部向けマニュアルも探す

    Look for external-facing manuals as well 最新がどれか把握する Identify the latest version Wordで書かれていたらテキストに変換する Convert Word documents into text. ◼内部向けならAIに食わせたいのでMarkdown(テキストベース)にする Convert internal documents to Markdown so they can be used with AI もし設計書がなければソースコードを元に作る If no design documents exist, create them from the source code © 2019-2026 OPTiM Corp. All rights reserved. 40
  26. 設計書とソースコードの食い違い Discrepancies Between Design Documents and Source Code 設計書とソースコードの食い違いを見つけた どうする?

    You find a discrepancy between the design documents and the source code. What do you do? © 2019-2026 OPTiM Corp. All rights reserved. 41
  27. 設計書とソースコードの食い違い Discrepancies Between Design Documents and Source Code 実装の経緯がわかる? Can

    you trace the history behind the implementation? © 2019-2026 OPTiM Corp. All rights reserved. 43
  28. 設計書とソースコードの食い違い Discrepancies Between Design Documents and Source Code true 実装の経緯がわかる?

    Can you trace the history behind the implementation? 判断可能 Enough information to decide © 2019-2026 OPTiM Corp. All rights reserved. 44
  29. 設計書とソースコードの食い違い Discrepancies Between Design Documents and Source Code true 実装の経緯がわかる?

    Can you trace the history behind the implementation? 過去と現在で状況の差分を取る 判断可能 Enough information to decide $ diff original_intent current_state - 当時の経営判断 Business decisions at the time - 当時の顧客要件 Customer requirements at the time - 当時の技術的制約 Technical constraints at the time - 単なる実装ミス A simple implementation mistake + 現在の事業方針 Current business direction + 現在の利用実態 Current usage patterns + 現在の本番環境の動作 Current production behavior + 現在の技術的制約 Current technical constraints $ decide © 2019-2026 OPTiM Corp. All rights reserved. 45
  30. 設計書とソースコードの食い違い Discrepancies Between Design Documents and Source Code true 実装の経緯がわかる?

    false Can you trace the history behind the implementation? 判断可能 Enough information to decide © 2019-2026 OPTiM Corp. All rights reserved. 46
  31. 設計書とソースコードの食い違い Discrepancies Between Design Documents and Source Code true 実装の経緯がわかる?

    false Can you trace the history behind the implementation? 判断可能 考古学 Enough information to decide Time for archaeology! © 2019-2026 OPTiM Corp. All rights reserved. 47
  32. 設計書とソースコードの食い違い Discrepancies Between Design Documents and Source Code true 実装の経緯がわかる?

    false Can you trace the history behind the implementation? 時と場合によって変わる It depends on the situation 基本は現行コードの挙動に合わせることが多い We usually end up matching the current code behavior. 判断可能 でも設計がきれいな場合は 設計に合わせることも稀にある Enough information But if the design is cleaner, to decide 考古学 Time for archaeology! we occasionally match the design instead. © 2019-2026 OPTiM Corp. All rights reserved. 48
  33. 設計書とソースコードの食い違い Discrepancies Between Design Documents and Source Code true 実装の経緯がわかる?

    false Can you trace the history behind the implementation? 判断可能 考古学 Enough information to decide Time for archaeology! © 2019-2026 OPTiM Corp. All rights reserved. 49
  34. 仕様書とソースコードの食い違いの例 For example Rails 2でGETとPOSTを区別しない書き方をしていた map.connect ':controller/:action/:id' In Rails 2,

    the code did not distinguish between GET and POST. map.connect ':controller/:action/:id.:format' © 2019-2026 OPTiM Corp. All rights reserved. 50
  35. 仕様書とソースコードの食い違いの例 For example Rails 2でGETとPOSTを区別しない書き方をしていた map.connect ':controller/:action/:id' map.connect ':controller/:action/:id.:format' In

    Rails 2, the code did not distinguish between GET and POST. The specification listed GET, so we changed the code to GET only. 仕様書にはGETと書かれていたのでGETに修正した get ':controller(/:action(/:id))' get ':controller(/:action(/:id(.:format)))' © 2019-2026 OPTiM Corp. All rights reserved. 51
  36. 仕様書とソースコードの食い違いの例 For example Rails 2でGETとPOSTを区別しない書き方をしていた map.connect ':controller/:action/:id' map.connect ':controller/:action/:id.:format' In

    Rails 2, the code did not distinguish between GET and POST. The specification listed GET, so we changed the code to GET only. 仕様書にはGETと書かれていたのでGETに修正した In practice, some clients were get ':controller(/:action(/:id))' calling the endpoint with POST or get ':controller(/:action(/:id(.:format)))' PATCH. 実際にはPOSTやPATCHで叩いてくるクライアントが存在した 仕様はGETのみだがPOSTを塞いでいなかったため、 制限すると既存クライアントが接続できなくなる → 仕様書のほうを修正した The specification allowed only GET, but POST was not blocked; restricting it would have broken existing clients — so we updated the specification instead. match ':controller(/:action(/:id))', via: [:get, :post, :patch] match ':controller(/:action(/:id(.:format)))', via: [:get, :post, :patch] © 2019-2026 OPTiM Corp. All rights reserved. 52
  37. 仕様書とソースコードの食い違いの例 For example 実装には t.timestamp (sが脱字している)と書かれていた The code had t.timestamp

    (the trailing "s" was missing). create_table :entries do |t| … t.timestamp end class AddCreatedAtToEntries < ActiveRecord::Migration[8.0] def self.up add_column :entries, :created_at, :datetime end end © 2019-2026 OPTiM Corp. All rights reserved. 53
  38. 仕様書とソースコードの食い違いの例 For example 実装には t.timestamp (sが脱字している)と書かれていた The code had t.timestamp

    (the trailing "s" was missing). create_table :entries do |t| … Rails 2: Ignore t.timestamp Rails 8: ERROR! end class AddCreatedAtToEntries < ActiveRecord::Migration[8.0] def self.up add_column :entries, :created_at, :datetime end end © 2019-2026 OPTiM Corp. All rights reserved. 54
  39. 仕様書とソースコードの食い違いの例 For example 実装には t.timestamp (sが脱字している)と書かれていた The code had t.timestamp

    (the trailing "s" was missing). create_table :entries do |t| … Rails 2: Ignore t.timestamp Rails 8: ERROR! end class AddCreatedAtToEntries < ActiveRecord::Migration[8.0] def self.up add_column :entries, :created_at, :datetime end end 仕様書は作成日(created_at)のみが記載されていた 明らかな誤字だが、これをtimestampsに修正すると 更新日(updated_at)も追加されて マイグレーションがおかしくなる → 仕様書を優先した © 2019-2026 OPTiM Corp. All rights reserved. The specification documented only a creation date (created_at). It was an obvious typo, but changing it to timestamps would also add an update date (updated_at) and break the migration. We followed the specification. 55
  40. 一気に上げるか少しずつ上げるか Upgrade All at Once or Incrementally? When Upgrading All

    at Once When Upgrading Incrementally  Code < 10k lines*  Code > 30k lines*  Rewrite from scratch  Many Gems ◼ Rails 2 → 8 は rails new して ファイルをコピーしたほうが早い For a Rails 2 → 8 upgrade, it is faster to run rails new and copy the files over.  挙動が変わってほしくない We don’t want the behavior to change. ◼ 古いバージョンに戻さないと いけなくなったときに 少しずつ上げているのと 変わらない If we have to go back to an older version, it’s effectively no different from upgrading incrementally. * コード量は経験則による目安です © 2019-2026 OPTiM Corp. All rights reserved. 62
  41. 一気に上げるか少しずつ上げるか Upgrade All at Once or Incrementally? When Upgrading All

    at Once When Upgrading Incrementally  Code < 10k lines*  Code > 30k lines*  Rewrite from scratch  Many Gems ◼ Rails 2 → 8 は rails new して ファイルをコピーしたほうが早い For a Rails 2 → 8 upgrade, it is faster to run rails new and copy the files over. 今回のプロダクトは コード量も小さく一気に上げた This product had a small codebase, so we upgraded it all at once. * コード量は経験則による目安です  挙動が変わってほしくない We don’t want the behavior to change. ◼ 古いバージョンに戻さないと いけなくなったときに 少しずつ上げているのと 変わらない If we have to go back to an older version, it’s effectively no different from upgrading incrementally. © 2019-2026 OPTiM Corp. All rights reserved. 63
  42. ローカルでも動くように整備しよう もちろんRails 2で Let’s get it running locally, too. On

    Rails 2, of course. ↑skytomo (VRの姿) © 2019-2026 OPTiM Corp. All rights reserved.
  43. 普通にRails 2のセットアップをお願いすると 怒られるので今が2010年代ということを教えます If you simply ask AI to set

    up Rails 2, it will complain—so tell it that it’s the 2010s. © 2019-2026 OPTiM Corp. All rights reserved.
  44. 過去のRailsをAIで動かす例 docker compose up –d → error AIを使う bundle exec

    ruby script/server → OK Use AI © 2019-2026 OPTiM Corp. All rights reserved. 72
  45. テストカバー率を上げてから Rails バージョンアップしないと 検証が大変になる If we don’t improve test coverage

    before upgrading Rails, verification will become much more difficult. © 2019-2026 OPTiM Corp. All rights reserved.
  46. テストを追加しましょう もちろんRails 2で Let’s add more tests. On Rails 2,

    of course. ↑skytomo (VRの姿) © 2019-2026 OPTiM Corp. All rights reserved.
  47. AIを導入すると解決すること What AI Can Solve 今までRails 2→8というようなアップデートは厳しかった Upgrading from Rails

    2 to Rails 8 used to be extremely difficult. ◼昔の環境が容易に構築できるようになった! We can now easily recreate legacy environments! ◼昔のコードが読める・書けるようになった! We can now read and write legacy code! ◼昔のテストが書けるようになった! We can now write tests for legacy code! © 2019-2026 OPTiM Corp. All rights reserved. 81
  48. AIを導入しても解決しないこと What AI Can’t Solve AIは入って間もない中途社員 AI is like an

    experienced developer who has just joined the company. ドメイン知識はないけどコードの知識はある It knows how to code, but lacks domain knowledge. ドメイン知識をどうするか So, how do we provide that domain knowledge? ドメイン知識は人間側もないんだよな The problem is, we humans may not have it either. やはり調査が大事 That’s why investigation remains essential. © 2019-2026 OPTiM Corp. All rights reserved. 82
  49. EoLの流れ The EoL Process 商品サイト、リポジトリ、 Find the product site, repository,

    ticket system, and documentation. チケット管理、ドキュメントを探す リポジトリのブランチを探す 見積もりのための調査をする 見積もりを出す Find the relevant branches in the repository. Investigate in order to prepare an estimate. Provide the estimate. ドキュメントを整備する Get the documentation in order. 既存も手元で動かせるようにする Get the existing system running locally. Implement tests. テストを実装する コード修正を行う Make the code changes. © 2019-2026 OPTiM Corp. All rights reserved. 84
  50. まとめ コード修正より調査 Prioritize investigation over code changes. 名前だけを信用せず、コードをエビデンスにする Don’t trust

    names alone. Use the code as evidence. SVN → Git 既存環境も新規環境も手元の開発環境で動かせるようにする Make both existing and new environments runnable locally. テストがカバーされているか確認する Check whether the code is covered by tests. ◼されていなければEoL対応前にテストを追加する If not, add tests before the EoL work. © 2019-2026 OPTiM Corp. All rights reserved. 85
  51. バージョンアップ結果 (Rails 2→8, Ruby 1→3) 対象コードの規模 変更量 Amount of change

    Size of the target code ◼ Code Diff: +4k –3k ◼ Code: 7.5k ◼ Gem: 16 → 35 ◼ Gem: 16 残課題 Remaining work 工数 ◼調査: 約1.2人月 ◼開発: 約2.0人月 ◼検証: 約2.0人月 ◼EoL対応開始の契機をルール化する Define rules for when to start EoL remediation Investigation: approx. 1.2 person-months Development: approx. 2.0 person-months Verification: approx. 2.0 person-months © 2019-2026 OPTiM Corp. All rights reserved. 86