Ruby on Rails
イベント
マガジン
技術ブログ
こんにちは、タイミーのバックエンド/Webフロント基盤チーム マネージャーの新谷( @euglena1215 )です。 先日開催された RubyKaigi 2026 に参加してきました。その中で特に気になったのが、Shopify の Alexandre Terrasa さんによる「 Blazing-fast Code Indexing for Smarter Ruby Tools 」という発表です。 この発表では rubydex という Rust 製の Ruby Code Indexer が紹介されていました。RubyLSP や Tapioca に統合することで最大10倍の高速化と2倍のメモリ削減を実現したという内容でした。また、Ruby ツールのための統一的なコードインデックス基盤としてのビジョンも示されていました。Shopify の Ruby DX チームが9名関わっているということで、Shopify への rubydex への本気度が伺えます。 発表の中では、Experimental ながら MCP サーバー(rubydex-mcp) も提供されていることが紹介されていました。Claude Code などの AI アシスタントからセマンティックにコードベースを検索できるようになっています。 AI Coding Agent にコードベースを調査させると、 Grep → Read → また Grep …というループが延々と続き、トークンがみるみる消費されていきます。rubydex-mcp を使えば、クラス定義やリファレンス、継承ツリーといった構造的な情報を、1回の MCP ツール呼び出しで取得できます。そのため、このループを大幅に削減できそうです。 実際にどの程度効果があるのか、タイミーのバックエンドリポジトリで定量的に検証してみました。 rubydex とは rubydex は Shopify が開発した Ruby Code Indexer です。 github.com Rust 製の Indexer がコードベースを解析し、MCP(Model Context Protocol)サーバーとして以下のツールを提供します。 ツール 機能 search_declarations 名前によるファジー検索(クラス、モジュール、メソッド、定数) get_declaration 完全修飾名による定義情報の取得(ドキュメント、祖先チェーン、メンバー) find_constant_references 定数の参照箇所をコードベース全体から検索 get_descendants クラス/モジュールの継承ツリーを取得 get_file_declarations ファイル内の構造一覧 codebase_stats コードベース全体の統計情報 通常、AI Coding Agent がコードベースを調査する際は grep や find でファイルを探し、 Read で中身を読み、また grep で次のファイルを探し…というループを繰り返します。rubydex を使うと、このループの多くが1回の MCP ツール呼び出しで完結できる可能性があります。 検証方法 概要 claude -p (Claude Code の非インタラクティブモード)を使い、rubydex あり/なし の2条件で同じプロンプトを実行し、トークン消費量と回答品質を比較しました。 検証環境 ツール:Claude Code CLI ( claude -p ) モデル:claude-sonnet-4-6 rubydex_mcp バージョン:0.1.0 対象リポジトリ:タイミーのバックエンド(モジュラーモノリス、70パッケージ) 条件の制御 外部要因を排除するため、以下の共通オプションを使用しました。 claude -p "<prompt>" \\ --output-format json \\ # トークン使用量を含む JSON 出力 --model sonnet \\ # モデル固定 --bare \\ # hooks, CLAUDE.md 等を無効化 --strict-mcp-config \\ # .mcp.json を無視し引数の MCP 設定のみ使用 --mcp-config <config> \\ # 条件別の MCP 設定 --tools "Read,Bash,Edit" \\ --no-session-persistence --bare で CLAUDE.md の自動読み込み等の副作用を排除し、 --strict-mcp-config により MCP サーバーの有効/無効を制御しています。これにより、2条件間の差は rubydex の有無のみになります。 プロンプト rubydex のツール群が効果を発揮しそうな質問を5種類用意しました。 ID プロンプト class_hierarchy XXXモデルのクラス継承チェーンと、includeしているモジュールの一覧を教えてください。それぞれのモジュールがどのファイルで定義されているかも含めてください。 find_references YYYモデルがコードベース全体でどこから参照されているか調査してください。参照元をコントローラ、モデル、サービス等のカテゴリ別に分類して一覧にしてください。 descendants ApplicationRecordを継承しているクラスの一覧を取得し、packs/ディレクトリ配下のパッケージごとに何個のモデルが存在するか集計してください。上位10パッケージを表示してください。 method_investigation XXXモデルに定義されているpublicインスタンスメソッドのうち、名前に'status'を含むものをすべてリストアップしてください。各メソッドの定義場所(ファイルパスと行番号)と、そのメソッドが何をしているかの簡単な説明を付けてください。 codebase_overview このRailsプロジェクトのpacks/ディレクトリ配下のパッケージ構成を調査してください。各パッケージに含まれるモデル数、主要なクラス名を一覧にし、パッケージ間の依存関係で特に密結合なものがあれば指摘してください。 各条件 × 各プロンプトで5回ずつ、合計50回実行しました。LLM の出力は非決定的なので、複数回実行して平均を取ることでばらつきの影響を軽減しています。 結果 トークン消費量 プロンプト rubydex なし(平均トークン) rubydex あり(平均トークン) 変化率 class_hierarchy 144,076 85,958 -40.3% codebase_overview 1,187,722 664,761 -44.0% descendants 46,501 165,795 +256.5% find_references 770,404 332,369 -56.9% method_investigation 986,840 636,411 -35.5% 5つ中4つのプロンプトで 35〜57% のトークン削減 を達成しました 🎉 コスト・速度 プロンプト コスト変化 実行時間変化 ターン数変化 class_hierarchy -16.7% -48.6% -35.4% codebase_overview -34.3% -19.6% -13.7% descendants +294.6% +261.0% +62.7% find_references -33.5% -19.0% -11.9% method_investigation -30.7% -50.1% -38.1% ターン数(エージェントのツール呼び出し回数)の削減がトークン削減の主因です。rubydex のセマンティック検索が Grep → Read の繰り返しを置き換えることで、エージェントループが短縮されています。 回答品質(LLM-as-a-Judge) トークンが減っても回答品質が下がっては意味がありません。別の Claude セッションを立ち上げ両条件の回答を渡し、正確性・網羅性・有用性の3観点で5点満点のスコアリングを行いました。 プロンプト rubydex なし(平均) rubydex あり(平均) 差分 class_hierarchy 4.33 4.00 -0.33 codebase_overview 4.33 4.00 -0.33 descendants 3.00 4.67 +1.67 find_references 4.00 4.00 0.00 method_investigation 3.33 4.33 +1.00 平均 3.80 4.20 +0.40 回答品質はむしろ改善しています 👏 Judge のコメントから見えた傾向を簡単にまとめます。 rubydex ありで改善した点(正確性) rubydex なしの場合、grep の結果をもとに関連しそうなクラスやメソッドを補足情報として列挙する傾向があった。目視では誤情報は確認できなかったが、裏取りが不十分な状態で情報を出しているため信頼性の判断がしにくい( method_investigation など) rubydex ありではインデックスに基づいた情報を返すため、出力の根拠が明確になっている rubydex なしが勝った点(網羅性・有用性) grep ベースの調査は探索範囲が広いため、rubydex が返さないカテゴリ(Policy、Mailer 等)の参照元も拾えていた( find_references ) rubydex なしの回答はファイルのフルパスや構造図を含むなど、開発者がすぐに使える形に整理されている傾向があった( class_hierarchy , codebase_overview ) 総じて、 rubydex ありは正確性で優位、rubydex なしは網羅性で優位 という傾向が見られました。また、いくつかのプロンプトの回答を目視でも確認しましたが、rubydex ありで明らかにおかしな内容を回答しているケースは見られませんでした。 descendants が悪化したケース 唯一、 descendants プロンプトではトークンが +256.5% と大幅に悪化しました。 このプロンプトは「ApplicationRecord の子孫クラスをパッケージ別に集計する」という内容です。rubydex の get_descendants ツールは全子孫を忠実に返します。(我々の環境では346クラス)一方、rubydex なしの場合は grep -r "< ApplicationRecord" のような検索で主要なものだけを拾うため、結果的にトークンが少なく済んでいました。 つまり、 大量の結果を返すような網羅的な検索では、rubydex がかえってトークンを増やす ケースがあります。ただし、品質面では rubydex ありの方が +1.67pt と最も大きく改善しており、正確性とのトレードオフと言えます。 まとめ 5つ中4つのプロンプトで 35〜57% のトークン削減 と 17〜34% のコスト削減 を達成しつつ、回答品質は LLM-as-a-Judge の評価で同等以上(5点満点で 3.80 → 4.20)でした。特に「クラスの参照元を探す」「メソッドの定義場所を調べる」といった構造的な検索タスクで効果が顕著です。 一方、全件取得のような網羅的検索ではトークンが増えるケースもあり、万能ではありません。rubydex が提供するツールの特性を理解した上で導入すると、より効果的に活用できそうです。 また、現状 rubydex-mcp を利用するには Rust ツールチェーン(cargo)が必要で、ソースからのビルドが求められます。開発環境の依存が増えることになるため、チーム全員が使える形に整備するかどうかはもう少し見極めたいところです。とはいえ、トークン35〜57%削減という効果は十分に大きく、rubydex-mcp への期待はとても高まる結果となりました。 検証の制約 今回の検証にはいくつかの制約があります。結果を解釈する際の参考にしてください。 --bare モードでの検証 : CLAUDE.md 等が無効化されているため、通常利用時とはベースのトークン消費量が異なります キャッシュの影響 : 実行順序や間隔によってキャッシュヒット率が変わるため、コスト比較は参考値です 回答品質の評価 : LLM-as-a-Judge による自動評価のみで、正解データとの突合は行っていません プロンプトの偏り : rubydex が得意そうなタスクを選んでいるため、実際の利用での改善幅はこれより小さくなる可能性があります
はじめに こんにちは。プロダクト開発部 転職開発チームでエンジニアリングマネージャーをしている松村( @shakemurasan )です。 2026-04-22(水)から2026-04-24(金)までの3日間開催されているRubyKaigi 2026に現地参加しています。 rubykaigi.org この記事は、Day1 13:00-13:30のkoicさんのセッション『Exploring RuboCop with MCP』について、事前準備編と当日編(セッション当日に残したメモと感想)を1本にまとめたものです。 事前準備編にはAIによる予想が含まれるため、実際のセッション内容と一致するとは限らない点をあらかじめ断っておきます。 はじめに 事前準備編 koicさんの人となり AIに予想させてみたら、本人告知で焦点が絞れた 本人おすすめの教材とPRを少し覗いた 当日編 前半: MCP Ruby SDKとStreamable HTTP 後半: この1年間の試行錯誤 結びへ: 決定性と非決定性、そしてElicitation 聴き終えて腹落ちしたこと おわりに 事前準備編 koicさんの人となり koicさんはRuboCopのトップコミッターで、2025年にはMCPの公式Ruby SDK ( modelcontextprotocol/ruby-sdk ) のメンテナーにも加わっています。 github.com そこまでの道のりはFindy Engineer Labの取材記事『 365日欠かさずコミットを積む。なぜRuboCopコミッター伊藤浩一はOSSと向き合い続けるのか 』と、直近のお話はご本人のブログ『 MCPの公式Ruby SDKのメンテナーに加わった 』で詳しく綴られています。 findy-code.io koic.hatenablog.com 個人的な話をすれば、私がRubyを書き始めて数年の頃、地域のRubyコミュニティで何度かkoicさんをお見かけし、ジュニア時代の自分に刺激をくれた方の一人でもあります。 AIに予想させてみたら、本人告知で焦点が絞れた セッションタイトルだけでは論点が見えにくかったので、実は事前に予習の材料として、AIにkoicさんの直近のPRやIssueをもとに内容を予想させていました。 返ってきたのは大きく3通りの案でした。 1つ目は、stdio実装とMCP primitives(tools / resources / prompts)の写像を中心に据える構成。 2つ目は、MCPのtool annotationとRuboCopのCop属性の対応を核に据える構成。 3つ目は、Streamable HTTPを軸に据え、組織運用論にまで広げていく構成。 いずれもkoicさんの公開PRやIssueから拾えそうな筋ではあり、最初は「なるほどこのどれかだろうな」と眺めていました。 その後、koicさんご本人が『 RubyKaigi 2026に登壇します 』で背景と予習の案内をすでに公開されていることに気づきました。 koic.hatenablog.com 本人告知で軸に置かれていたのは「RubyツールチェインへのAI時代の課題提起」で、Streamable HTTPは副題として明示されていました。 一方で、tool / resource / promptといった「よく溢れている情報」は深掘りしない、とも明言されています。 AIの予想と本人告知を観点ごとにまとめると、次の通りです。 観点 AIの予想 本人告知 中心軸 RuboCop実装詳細 / MCP primitivesの写像 RubyツールチェインへのAI時代の課題提起 Streamable HTTP 1案の中心、他2案では末尾に触れる程度 副題として明示 、講演の大きなトピック tools / resources / prompts 写像の中心概念として扱う 「よく溢れている情報」として深掘りしない旨を明言 当たっていたのは「Streamable HTTPが主要トピックの1つ」と見立てていた点で、大きく外れたのは「tool / resource / promptを写像の中心概念として扱う」という方向性でした。 AIの予想は世に広く出回っている話題の重心に引っ張られやすく、本人が「あえて深掘りしない」と宣言していた領域こそがむしろ中心に置かれていた、というコントラストになります。 そのおかげで、当日聞きに行くべき焦点が一気に絞れました。 本人おすすめの教材とPRを少し覗いた 本人告知で紹介されていた教材のうち、RubyWorld Conference 2025でのkoicさんの登壇アーカイブに目を通しました。 「なぜstdioだけでは足りず、双方向のHTTP通信が必要なのか」という道筋が登壇の流れで追えるため、セッション前のウォームアップに助かりました。 当日編 本編は事前告知どおりの2部構成で、前半がMCP Ruby SDKの話、後半がRuboCop x MCPの話でした。 なお、当日のセッション資料は『 Exploring RuboCop with MCP 』としてすでに公開されています。 speakerdeck.com 以降は、現地で受け取った温度感の記録として読んでもらえればと思います。 前半: MCP Ruby SDKとStreamable HTTP Ruby SDKはもともとShopify社内で少人数のエンジニアが始めたもので、koicさん自身もRuboCopを念頭に早い段階から参画し、コミッターに招かれたのち、 mcp gemとして公開された、という経緯が紹介されました。 MCPにはTier1〜3のランクが定義 されていて、現在のRuby SDKはTier3。 Tier1を目指していく、と明確に宣言していました。 本題のtransportsの話では、規格としてstdioとStreamable HTTPの2つが並びます。 stdioの単純さはさらりと触れ、時間が割かれたのはStreamable HTTPのほうでした。 HTTPの規格のままで、WebSocketのような独自プロトコルに寄らずに双方向通信を成立させる。 実装はRackアプリケーションとして組んでおり、HTTPで叩かれたタイミングでMCPセッションIDを払い出してセッションを確立し、Queueを介してやり取りを何往復も成立させる。 1リクエスト1レスポンスではなく、1リクエストを起点にサーバー・クライアント間で通信が走る、という絵が丁寧に描かれていきます。 手を動かさないと実感が湧きにくい領域ですが、Rackの上に素直に乗っているという話を聞いた瞬間、普段触っているWeb技術の延長線上で捉えていい話なのだ、と急に距離が近く感じられました。 そして前半の締めでkoicさんが置いた次のようなニュアンスの一言が、個人的に一番刺さっています。 「AIになってガラッと変わったと思われるが、Linuxであるとか低レイヤの世界は何も変わっていなくて、我々はその上で開発をしているに過ぎない」 弊社でもたびたび話題に上がる「AIの台頭によりエンジニア自身にとってはむしろ基礎が大事になっていく」という考え方と一致しており、強く共感しました。 後半: この1年間の試行錯誤 後半はトーンが少し変わりました。 「1年間いろいろ試行錯誤してきたが、うまくいかなかったことが多かった。その話をします」とkoicさんが率直に切り出します。 成功譚ではなく、試行の経過と現在地の共有だ、というモードに切り替わりました。 最初のアイデアはシンプルで、RuboCopの結果をJSON構造でMCP化すればAIフレンドリーになって良いのではないか、というものでした。 しかし実際に手を動かしてみると、RuboCopはそもそも著名なgemなので、AI側もすでに相当学習していたように感じられた、と振り返ります。 わざわざMCPの皮を被せなくても、ある程度のことは既にできてしまう相手だった、ということです。 アイデアを広く募集して議論もしたものの、寄せられたものをそのまま実装して全員が喜ぶ機能になる自信は持てなかった、とも続きます。 結びへ: 決定性と非決定性、そしてElicitation そこから結びに向けて「RuboCopはこれまで、インプットに対して結果が一意に定まるものだった」と改めて位置づけ直されます。 「決定性こそがLinterとしての価値だった」という前提を言葉にしたうえで、そこに非決定性を持つLLMを組み合わせたら何ができるのか、と続きました。 具体例として並べられたのは、LLM側に委ねるSamplingと、ユーザーに聞き返すElicitationでした。 どちらもサーバーからクライアントに問い合わせを返せる仕組みですが、自分の耳に特に残ったのはElicitationのほうです。 ユーザーに対して定まったフォーマットの質問と回答フォームを返せる仕組みで、「この修正、どう進めたい?」と聞き返す余地をMCPの上で作れる、という話として置かれていました。 決定性のあるRuboCopの流れのなかに人間に問いを返すポイントを差し込み、そこを挟んだ非決定性を許容する。 決定性を捨てる話ではなく、どこで問いを立て、どこで非決定性を受け入れるかの設計の話として受け取りました。 この時私が思い出したのは、自チームでRuboCopのルール改廃を議論する時の話です。 一元的に適用するか悩ましいものが出てきたとき、その悩みには既存コードの暗黙的な規約、各エンジニアの思想や経験、copとして定義されているベストプラクティス、と様々な要素が絡んでいます。 これらは機械的に一意には定められないものです。 この統治過程にLLMが自然な形で介入し、対話を経てLinterに落とし込んでいくのはありそうな役割だと感じました。 (それをRuboCopの機能として提供されてユーザーが嬉しいかはさておき) ちなみにMCPの規格としてElicitationが発表された当時、弊社でも管理者向けのLocal MCP Serverにこれを組み込む事例があり、『 生成AI時代のサービス運営管理 - MCP Server for Administratorの実践 - 』(2025年9月16日公開)としてまとめられています。 tech.findy.co.jp 一方通行になりがちなMCPのやりとりに confirm / approveのステップを挟むという考え方は、koicさんが当日RuboCopの文脈で示したElicitationの位置づけとそのまま重なるものでした。 聴き終えて腹落ちしたこと 少なくともセッションの内容は「RuboCop x MCPのベストプラクティスがバシッと決まっている」わけではないということです。 むしろ、当事者として踏み抜いた人しか持ち得ない肌感を、苦労ごと公開してもらった30分だった、というのが近いと思います。 文字にするとシンプルですが、現場で聴講した皆さんにはkoicさんの試行錯誤と苦労が生々しく伝わっていたのではないかと思います。 現地参加する醍醐味をこういうところにも改めて感じました。 MCP化が思ったほど刺さらなかったこと、アイデアを集めても一意の答えに収束しないこと、Human in the Loopをどう設計するかが実装より先にあること。 どれも、ドキュメントや事例紹介を眺めていても掴めない、当事者として踏み抜かないと分からない種類の手触りです。 前半と後半を通して一本の線で繋がっていたのは、RubyツールチェインをAI時代にどう位置づけ直すかという問いだったように思います。 Streamable HTTPという具体的な技術基盤の話と、RuboCop x MCPという応用の試行錯誤、そして「低レイヤの世界は何も変わっていない」という立ち位置。 3つが重なって、Rubyのツール群とAIの関係をReframingする、という輪郭が浮かび上がる構成になっていたように私は感じました。 先頭に立ってこれだけの領域を踏み抜いてきたkoicさんへは、感謝と尊敬の気持ちでいっぱいです。 Ruby SDKへの貢献はRuboCop単体の話に留まらず、Rubyツール群全体が立つ足場を整える仕事なのだろう、と自分には受け取れました。 本セッションはAI時代にもRubyが最前線で使われる言語であり続けるための重要な歩みの1シーンを見せてくれたのだと改めて感じました。 おわりに AI時代だからといって銀の弾丸はなく、Rubyツールチェインも、HTTPやRackやQueueといった土台の上で地道に積まれていきます。 前半の締めの「低レイヤの世界は何も変わっていなくて、我々はその上で開発をしているに過ぎない」という言葉は、AIに振り回されずに使う側に回るのに必要なのは近道ではなく基礎だ、ということを改めて思い出させてくれました。 ファインディでは、一緒にRubyやRailsの開発をしてくれる仲間を募集しています。 興味のある方は、ぜひこちらからチェックしてみてください! herp.careers
はじめに コンスタナイズー!(気さくな挨拶) ココナラのDevOpsグループCREチームのy.s.(@inu_no_hou)です。 皆さん、constantize というメソッドをご存知でしょうか。文字列からRubyの定数(クラス)を動的に解決するActiveSupportのメソッドです(ぎえー)。 私がココナラの会計システム(のちに自らマイクロサービス化することになる)のコードで初めてこれを見たとき、正直に言うと震えました。 def factory(acct_event, option = {}) klass = acct_event.event_code.gsub(/^eve
動画
該当するコンテンツが見つかりませんでした













