タイミーの江田、徳富、神山、亀井、桑原、志賀です。 KaigiPass という制度を利用して Kaigi on Rails 2025 に参加してきました。タイミーは昨年に引き続きスポンサーをさせていただき、今年はなんと幸いなことにブースも出させていただきました。今回はそんな Kaigi on Rails 2025 の参加レポートを KaigiPass を利用したメンバーで記述していこうと思います。
2分台で1500 examples 完走!爆速 CI を支える環境構築術
Hiroshi Tokudomi
https://kaigionrails.org/2025/talks/falcon8823/#day1
「2分台で1500 examples 完走!爆速 CI を支える環境構築術」というタイトル通り、CI をどのように高速化していくかについての発表でした。
弊社でも現在 self-host runner を使って GitHub Actions 上で CI を回しており、2 万 2 千件のテストを平均 9〜10 分程度で実行しています。CI は短ければ短いほどいいものなので、このセッションタイトルを見たときに「これは絶対に見に行こう」と思ったのですが、まさに期待通り参考になる内容でした。
テストを並列に分割して実行する方法として Knapsack Pro が紹介されており、自分たちが使っている split-test と比較しながら聞くことができました。Knapsack Pro は実行時間の履歴をもとに分割を最適化できるとのことで、今後検討してみたいと思います。
また、EBS の I/O がボトルネックになることで CI が遅くなる話も印象的でした。弊社でも CI 実行が重なると I/O 使用率がギリギリまで上がることがあり、tmpfs を使うことで改善できる可能性があるのでは、とワクワクしながら聞いていました。
ちょうど最近 CI 基盤を self-host runner に移行したばかり(参考)ということもあり、「次はどこをチューニングできるか」と考えていたタイミングでのセッションだったので、個人的にはかなり刺さりました。CI をどう速くするかは日々の開発体験に直結するテーマなので、今回の学びを持ち帰って改善につなげていきたいです。
dynamic!
Keisuke Kuwahara
https://kaigionrails.org/2025/talks/moro/#day1
https://speakerdeck.com/moro/dynamic
1日目のキーノート「dynamic!」は、静的なアプローチとは対照的に、最初から完璧なゴールを目指すのではなく、継続的に変化していくプロセスを重視するテーマでした。
セッションでは、開発を細かく進めるための第一歩として、「ハッピーパス」の実装が重要だと強調されていました。ハッピーパスとは、ユーザーが使える「最小限かつ最もシンプルな機能」のことであり、これをまず実装することで、早い段階でフィードバックを得て、改善サイクルを回すことが可能になります。
特に印象的だったのは、開発者だけでなく、チーム全体で変化を起こしていくという考え方です。私自身、複雑な機能を実装する際、最初からすべてを網羅しようと時間をかけた結果、いざデモをしてみると多くのフィードバックをもらった、という経験があります。その時はできるだけ指摘をもらわないように実装しよう、という気持ちになっていましたが、今回の話を聞いて、動くものをいち早くチームメンバーやステークホルダーに確認してもらい、早くフィードバックを得ることの重要性を再認識しました。
またこれまでは、優秀なエンジニアほど、一発で完璧なプロダクトを作るものだ、と漠然と思っていましたが、実際は逆でした。経験豊富なエンジニアほど、最小限の開発から始め、段階的な改善を積み重ねていくのだと気づきました。
アジャイル開発は今のチームでは当たり前になっていますが、「動的に変化し続けること」の重要性を改めて深く感じました。完璧主義にとらわれて最初の実装に時間をかけるのではなく、変化を恐れずに、その時々で最もシンプルな方法を実践していきたいと思います。
「技術負債にならない・間違えない」 権限管理の設計と実装
Akitoshi Shiga
https://kaigionrails.org/2025/talks/naro143/#day2
Webサービスにおいて頻出の課題である権限管理に対して、自社のプロダクトで行った取り組みを発表されていました。
権限管理のありがちなアンチパターンとして、権限の判定が必要な場所で操作者の役割を判定するような実装についてあげられていました。
例: あるControllerのcreateアクション内でif admin?
役割を判定する場合は、判定する箇所が役割ごとに何ができるかを把握する必要があります。
役割ごとの権限は、サービス内容や事業環境の変化が激しい状況においてはすぐに複雑化します。
その上、この実装では権限を変更するたびに、すべての判定箇所に手を加えなければいけません。
その結果としてすぐに保守が困難になります。
そこで、役割=何者であるかではなく権限=何ができるか に依存すること、その上で、権限管理に必要な要素である「対象」「操作」「役割」「条件」に対する記述を分離・明文化した設計を発表されていました。
具体的には、module分けした「対象」ごとに「役割」のクラスを作り、「操作」に紐づいたメソッド内で「条件」を判定する実装を行っていました。
これによって、対象ごとに役割が操作を行うための条件が非常にシンプルになりました。
その結果、カスタマーサポートやプロダクトマネージャーがGitHubでコードを読んで理解できるようになり、社内からのエンジニアへの権限に関する問い合わせが0になったそうです。
所感として、操作する対象が増えるたびにすべての役割のクラスを作成する必要があるものの、条件というコアなロジックは一箇所に集中されるので保守しやすそうだと感じました。
また、権限という複雑なビジネスロジックを非エンジニアが理解できるほどシンプルにコードで表現されていることに感銘を受けました。
複雑なビジネスロジックにちゃんと向き合ってシンプルな表現を目指すことの効果と大切さを今一度実感しました。
Railsによる人工的「設計」入門
Yutaka Kamei
https://kaigionrails.org/2025/talks/nay/#day1
亀井です。万葉の大場さんのこちらのセッションが素敵だなと思ったので、このセクションを書かせていただいています。私なりにこの発表を解釈すると、設計がうまくなる方法について深掘りした内容だったのかなと思います。この AI 時代にコーディングを AI に任せることは増えてきた中で、人間が設計をできることの重要性がとても高まっています。そんな中で、どのようにしてもっとうまく設計ができるようになるのか?というのをご自身の偶然の経験から形式知にしてまとめてくださった内容でした。
完成したシステムを思い浮かべてそこから「逆算」して考えていくとよいのではないか?というのが重要そうでした。私の経験でも、ゴールを思い浮かべてそこに至るまでのマイルストーンを描きステップを重ねるというやり方がよいのではないか?ということを思っていたので非常に納得感があります。まさに全体から部分へ、という思考を行うことによってうまく設計ができる、という考え方ですね。たしかに、 Ruby on Rails が MVC をベースにしたフレームワークだからといって、モデル→コントローラー→ビューという順番に書く必要もないですし、むしろその順番で書くと全体が見えない状態で開発をすることになるので、次第につぎはぎだらけのコードが生成されてしまいます。その場しのぎのコードになってしまうと、やはりそれはそれで今後のメンテナンス性に影響してくるわけです。あるべき状態、あるいは本質的なゴールを描いてそこから「逆算」する、という考え方の言語化がとても素敵でした。
また、名付けの重要性について語っておられたのもよかったですね。 Ruby 界隈では「名前重要」というのはよく知られていると思いますが、設計の上でなぜ名付けが重要なのか?ということについての言語化もクリアでわかりやすかったです。たしか、コードのレベルではなく、抽象度の高いレベルで短い名前をつけながら考えを進めて「デザインパーツ」を取捨選択し「仮置き」することが重要というようなこともおっしゃっていたと思います。「仮置き」というワーディングがよいですね。たしかに、「決定」というと後戻りができない感じがしますが、「仮置き」というのは「変更の余地があること」を示唆する感じがして、日本人としてこういう日本語表現を利用できるのはとてもラッキーだなと思います。そういえば、「仮置き」で思い出しましたし、このセッションで参照されたキーノートの dynamic! にもあったように、オプショナリティーについて言及が最近増えましたね。「仮置き」という用語にもオプションというニュアンスを感じます。『Tidy First?』を読んで私なりにオプションについて理解をしているつもりでしたが、こうしていろいろな登壇を聞いて私なりの解釈もそこそこあってそうな予感がしてうれしさを感じています。みんな Kent Beck が好きですよね。私もです。
今改めてServiceクラスについて考える 〜あるRails開発者の10年〜
Yuki Eda (edy)
https://kaigionrails.org/2025/talks/joker1007/#day1
Ruby on Railsでアプリケーション開発に従事しているエンジニアであれば一度は通るであろうServiceクラス。2025年のこのタイミングでjokerさんがこのタイミングで発表を行う理由も気になり視聴しました。
冒頭で歴史的な経緯を含めて日本国内で布教した背景の考察や、『パーフェクトRuby on Rails』にてServiceクラスを題材に執筆された当時の意図、執筆後数年経ってからの[Qiitaでのエントリ](https://qiita.com/joker1007/items/25de535cd8bb2857a685)などに触れられつつ、Serviceクラスに対しては出来る限り使わない方が良いと結論づけられていました。理由は「開発統制の困難さを上回るメリットが得られない」とのこと。
この点、私も思い当たる節はあり、例えばFat Modelを解消する手段としてServiceクラスを選択していた過去があります。適切な命名付けをしたとしても、アプリケーションの成長や数年間の運用の過程で特定のドメインだけの処理で留まらずに肥大化したトランザクションスクリプトになる傾向があると思います。これはjokerさんも言及されていた「基準の作りにくさ」から来る部分や、適切なドメインモデリングを怠った結果の2つが大きな原因だと、発表を聞きながら改めて考えさせられました。
結局のところ、ビジネスにおける関心事を顧客やチームメンバーを交えながらシステム内でうまい具合に表現できるするか、その丁寧な抽象化と具体化の繰り返し作業が大事で、Serviceクラスもそうですし対抗馬として挙げられることの多いFormクラスも含めて、デザイン方法は表現技法の一つに過ぎないということですね。
発表の末尾のスライドの「正解はない、一緒に考え続けましょう」「ソフトウェア設計は継続的な営み」が非常に印象的で心に留めておきたいと思いました。
履歴 on Rails : Bitemporal Data Modelで実現する履歴管理
Daichi Kamiyama - dak2
https://kaigionrails.org/2025/talks/hypermkt/#day2
https://speakerdeck.com/hypermkt/history-on-rails-with-bitemporal-data-model
直近で履歴を残すかどうかの設計に頭を悩ませたことがあり、Bitemporal Data Model での履歴管理の良し悪しが気になったので、拝見させてもらいました。
履歴テーブルのパターンとして参考になるのは、一休さんの https://user-first.ikyu.co.jp/entry/history-table このスライドが非常に参考になると思っています。普通に“履歴”という概念を表現するのであれば、このスライドの内容に沿って場合分けしていけば多くの場合は網羅できるんじゃないかと思っています。
ただ、SmartHR さんが扱うドメインとして “従業員を起点とした変化” に向き合っていく場合、「あとから分かった出来事も正しい日付で反映したい」というニーズがあるようです。確かに言われてみればそうですよね。
レコードとして有効な期間(ex. 2025/09/26 までに役職が部長だった)と、操作時間の2つの時間軸で履歴を管理するコンセプトが Bitemporal Data Model です。有効な期間だけだと、そのレコードがいつ登録/無効になったかの事実が抜け落ちるので、2つの時間軸で管理しようという話のようです。
パッと直感的に思ったのは2つの時間軸を考慮しないといけないので、考えることが掛け算で増えてしまう懸念を持ちました。SQL も複雑になりそうですしね。後から有効な期間を追加したい場合に、有効期間が重複してはいけないと思うので、そこの制約を Model のバリデーション、Database の制約ともに考慮する必要はあるんだろうなとか。
スライドでも想定外の履歴データが作られていることがあり、原因調査に丸一日かかったという言及がされていました。基本的に INSERT されるはずなので、そこから問題となっているデータを特定するのに時間がかかるというのはあるんだろうなと。activerecord-bitemporal gem では visualizer 機能があり、レコードの履歴を可視化してくれるそうです。
有効期間の日付管理が timestamp だと時分秒の管理があるから、date 型に変更して運用容易性を担保したという話も興味深かったです。この部分で意図しないレコードが生まれるケースはありそうだなと思っていたところ、https://tech.smarthr.jp/entry/2025/09/12/115617 も拝見し、まさにその問題があったようですね。“履歴の一括出力後、Excelで適用日を編集するとExcelの仕様で時分秒の情報が「00:00:00」に丸められてしまう”、“例えば部署マスターの更新、並べ替え、削除、従業員部署の登録、更新などでは多数のモデルが同一トランザクションで更新されます。 このとき、適用日の時刻を固定して揃えないと、処理タイミングの僅かなズレによって適用日が秒未満の精度で異なった履歴が作成されてしまう” 、“同一適用日の更新において、社員番号と適用日の組み合わせでレコードを特定する際、ユーザーから秒未満を切り上げた日時を受け取り、秒未満を考慮して対象の履歴を探す” などなど、かなり負の側面を抱えていたようです。大変な移行だったようですが、とても意味のある移行だなと思いながら拝見しました。date 型だと unique 制約によって重複を弾きやすくなりますしね。
“履歴” を表現する1つの手段として Bitemporal Data Model を使ったリアルな声が公開されているのは、本当に嬉しいですね。とても参考になる話を聞けました。今後モデリングする際は、1つの手段として頭の片隅にインデックスを貼っておこうと思いました。
