Kaigi on Rails 2024 参加レポートvol.2 【#kaigionrails #RUNTEQ】
こんにちは!RUNTEQ講師兼エンジニアの清水です。
2024年10月25日と26日に行われた 「Kaigi on Rails 2024」 に参加させていただきました。今回は、Kaigi on Rails 2024に参加して学んだことや感じたことを共有したいと思います。
Day1 - 10.25 (Fri.) セッション
◆基調講演 Rails Way, or the highway
Palkanさんによる基調講演は、Rails Wayについて解説から始まりました。Rails Wayの特徴として、「MVC」「設定より規約」「複雑さの圧縮」 があり、Railsは0から1を作ることに長けています。しかし、1から先にいくための課題があるとおっしゃっていました。
具体的には、まずWebアプリケーションは「コントローラー」「モデル」「ビュー」と3つの工程がありますが、アプリケーションが成長していくにつれて、ビジネスロジックを格納するには足りなくなってしまい、さらにRailsだけではカバーしきれない隙間をカバーするためにgemなどを入れていくと、結果的にRails Wayから外れていく傾向があるとのことでした。
個人的には、Railsが0から1に強いことはイメージがありましたが、アプリケーションが成長していったときにRails Wayから外れてしまうことが具体的にイメージできていなかったので、とても勉強になりました。
その後、「Railsを習得し、拡張する」というテーマでRails Wayに沿った拡張するには抽象化レイヤーが必要であるとのお話がありました。
「抽象化レイヤーの間に明確な境界を引く」ためにレイヤードアーキテクチャの原則(**Presentation / Application / Domain / Infrastructure** レイヤーがあり)を参照することができ、Railsの抽象化を対応づけるお話もとても興味深かったです。
最後に抽象化レイヤーの導入例として 「Form Object」 の実装例を解説してくれました。
まだ理解しきれていない部分もありますが、抽象化レイヤーを実務に落とし込んだ実装にチャレンジしてみたいと思いました。
◆Railsの仕組みを理解してモデルを上手に育てる - モデルを見つける、モデルを分割する良いタイミング
次に、五十嵐邦明さんのモデルの見つけ方・分割のタイミングについての発表を聞きました。基調講演と近いお話しではありましたが、より実務よりの内容でとても勉強になりました。
まず、「モデルの見つけ方」 として 「イベント型モデルを探す」お話しがありました。イベント型モデルは、「行為を記録するモデル」であり、例としては Order(注文) / Shipment(出荷) / Payment(支払い) のようなものがあげられるとおっしゃっていました。
なぜイベント型モデルを探し出せると良いのかを疑問に思っていましたが、 「責務が適切なモデルに処理をかけて、複数のモデルにまたがる処理を書きたい問題が解消できる」「Rails Wayに乗った設計方法になっている」というメリットがあるとおっしゃっていて少し疑問が解消されました。
そして、Service層を入れるのはできるだけやめてほしいというお話しもありました。理由としては、Railsの特徴としてレイヤー分割を減らして書くコード量を減らす設計をしているので、Service層を増やすことはRailsの特徴を消す方向に働きかねないとのことでした。
他にもビジネスロジックをモデルとServiceオブジェクトのどちらに書くか迷いやすいことや、Serviceオブジェクト間でのメソッド共有が難しいこともデメリットとしてあげられていました。
後半は、「モデルを分割する良いタイミング」について説明がありました。この中で個人的に印象に残っているのが 「Fatモデル」の判断基準についてのお話です。私はコードの行数でFatモデルかどうかを判断していると思っていましたが、その基準ではあまり意味がないらしく、「そのまま書き続けるとしんどくなるとき」かつ「そのタイミングで良い分割方法があるとき」を基準とすると良いとのお話がありました。
またモデルを分割するタイミングについても詳しくお話しをしてくださったので、今後の開発時には意識して実装をしていきたいと思いました。
◆そのカラム追加、ちょっと待って!カラム追加で増えるActiveRecordのメモリサイズ、イメージできますか?
Asayama Kodaiさんのお話は、まだ私が実装しているときに意識できていない領域の内容で難しい内容ではありましたが、メモリサイズに意識を持つ良いきっかけになりました。
integerのカラムを増やすと224バイト増えることも初めて知りました。
◆リリース8年目のサービスの1800個のERBファイルをViewComponentに移行した方法とその結果
Naoyuki Kataokaさんのお話はViewComponentについてでした。個人的にまだViewComponentを使用した実装を行ったことがなかったのですが、ViewComponentを使用するメリットを実体験から分かりやすく解説してくださった。
ビューレイヤーの課題として、「パラメータ定義の曖昧さ」 「一貫性のないパラメータの渡し方」 「テンプレート内のロジックの多さ」を上げられており、直近で担当したプロジェクトの開発でも課題に感じていた部分と重なる点がありました。特に、ビューテンプレート内にロジックが多くあると可読性・保守性が低下してしまうのはとても共感できました。
そして、erbファイルからViewComponentに移行する方法の自動生成スクリプト作成のお話もとても興味深かったです。また、実際の開発現場ではよくある移行しながらも改修・追加の開発は継続して行われる場合も考慮している点がとても勉強になりました。
リリースフローに関しても安全にリリースするために、段階的なリリースを行ったお話が、「フィーチャーフラッグ」と「カナリアリリース」を行ったことがリアル感があり、とても参考になりましたし、今後こういった段階的なリリースが必要な場合に参考になるお話だったなと思いました。
◆ActionCableなら簡単? 生成 AIの応答をタイピングアニメーションで表示。実装、コスト削減、テスト、運用まで。
kaibaさんのお話はLLMのAPIのレスポンスを効率化してUXを向上させるという内容でした。レスポンスを1文字ずつタイピングアニメーションで表示する際に、文字の順序が保証されていない問題をindex番号をActionCableに伝えてフロントエンドで組み直す対処方法は今後活かせそうだなと思いました。
また、ローカル環境でLLMを動かすツールとして 「LM Studio」 というものがあるのも初めて知ることができました。ローカル環境でLLMをかなり簡単に動かすことができるようですので、LLM関連の実装を行う際には使用してみたいと思います。
◆現実のRuby/Railsアップグレード
Yuichi Takeuchiさんのお話は、Ruby/Railsのアップデートについて実体験を元に感じた課題についての内容だったので、身近に感じたと同時に変更に対して強いアプリケーションを開発することの大切さを再認識させられました。
アップグレードに必要な準備として、「RailsとRubyをセットでデプロイできるインフラ」 「テストの整備とテストを根付かせる仕組みづくり」 「エラーを通知する仕組みづくり」 「非推奨警告をなくし、発生を通知する仕組みづくり」 「ビジネス側との関係を密にし理解を得る」が必要とおっしゃっていました。
個人的には、「ビジネス側との関係を密にし理解を得る」 という項目のお話で、アップグレードは直接的に売上アップにつながるわけではないため、良い関係性を構築していないとスムーズなアップグレード作業が行えないという点がすごく納得しました。
また、アップグレードを行う際に保守されていないgemやモンキーパッチを適用しているgemがあるとバージョンによる依存関係を解決できない問題が発生したともおっしゃっていました。このお話を聞いて、gemを導入する際にはしっかりと調査をして慎重に判断することも大切だと思いました。
最後に、実際に行ったアップグレードの手順やそのとき発生した問題と解決策までお話してくださり、今後発生するであろうRails 8へのアップグレードの際に参考にさせていただきたいと思いました。
Day2 - 10.26 (Sat.) セッション
◆ActiveRecord SQLインジェクションクイズ (Rails 7.1.3.4)
Koji NAKAMURAさんはSQLインジェクションについてお話ししてくださりました。SQLインジェクションとは「SQL文の組み立て方法に問題があるとき、攻撃によってデータベースの不正利用を招く可能性がある」という内容からクイズを交えて、どのSQL文に脆弱性があるのか、そしてその対策までを分かりやすく説明してくださりました。
ActiveRecord SQLインジェクションクイズの問題で、`User.where("name = #{params[:name]}") ` は、`params[:name]` が直接SQLクエリに組み込まれているため脆弱性があるのは分かり、クイズに正解することはできましたが、`.exists?`を使用した` User.exists?(params[:id])` が脆弱性を持つということは知りませんでした。
また、RailsでのSQLインジェクションの防ぎ方のお話もあり、「SQLフラグメントを受け取るメソッドを一定把握する」「クエリメソッドへ外部入力(特にparams)を雑に渡さない」「クエリメソッドへ外部入力を渡すときは、sanitize_sql_array などの sanitize メソッドを組み合わせて使用する」** など、とても勉強になりました。
◆OmniAuthから学ぶOAuth 2.0
ykpythemindさんのOAuthについてのお話は、そもそも認証・認可とは「認証 : 個人を識別すること」 「認可 : 対象物に権限を与えること」というお話から、Googleログインの実装を元にしてOAuth 2.0の説明をしてくださりました。
個人的には、「OmniAuthは裏側で認証・認可のプロトコルに従った実装がされている」という内容のお話が認証系の知識が浅かったので勉強になりました。「OAuth 2.0はWebアプリの認可のためのプロトコル」で「OpenID ConnectはWebアプリの認証のためのプロトコル」であり、サードパーティログインをさせたい時のOmniAuthの裏側でやっていること、「クライアントからIDプロバイダに認証リクエストを送信する」→「認証レスポンスが返ってきたらトークンリクエストを送信する」→「返ってきたIDトークンを検証して認証し、必要に応じてアクセストークンを使用する」という認証フローの説明が分かりやすかったです。
◆Sidekiq vs Solid Queue
Rails 8.0からデフォルトになるSolid Queueを使った方が良いのかというお話をしてくださりました。
Sidekiqのメリットや、Solid Queueを選ぶべきケースについて説明してくださり、バックグラウンドワーカーの選定を行う際にとても参考になるお話でした。
ストレージに関しては、Solid QueueはアプリケーションのDBと相乗りできるため、小規模なサービスであれば管理しやすく便利だが、大量のジョブを扱うのであればRedisを使用するSidekiqの方が優位性があるとのことでした。また、機能については現時点ではSidekiqにあって、Solid Queueにはない機能(Batch処理、Rate Limiting、Encryption)がいくつかあるようです。
現状、小規模サービスではSolid Queueを使用し、DBを相乗りさせてRedisのコスト削減を図ることはあるかもしれないが、現在Sidekiqで困っていることがすぐに解決するわけではないとのことでした。
ただ、個人的にRails 8.0からデフォルトになるSolid Queueは、今後触っておきたいと思いました。
◆Data Migration on Rails
ohbaryeさんは、本番データ変更(data migration)についてのお話しをしてくださりました。個人的に、本番データの変更方法については何が正解なのかがあまり分かっていなかったのでとても参考になるお話でした。
data migrationで起きがちな課題として、「手作業にオペレーションミス、二次被害のデータ不整合」「データ変更に伴う障害、ユーザー対応」「プロジェクトごとに方法が違う、属人化」を挙げられており、どのプロジェクトでも似た課題を感じているのだなと思いました。
そして、data migrationのアプローチ方法として、gemを使用する方法もあることは知らなかったのと、その中でもmaintenance_tasksというgemが満足度が高かったというお話がありとても参考になりました。
また、data migrationのアプローチの選定ポイントについてもお話があり、各チーム・プロジェクトごとに評価項目を洗い出し、優先順位をつけてルールを作成していくことが大切とのことでした。
最後に
初めて技術カンファレンスに参加して色々なセッションを聞くことができ、理解できる点とまだ理解ができていない点がわかりました。また、全体的に実務向けのセッションが多く、エンジニア歴が浅い方でも楽しく聞けるのがすごく良かったなと思いました。
そして、今後いつになるか分かりませんが、プロポーザルを提出して登壇者としてKaigi on Railsに参加できることを目標として日々取り組んでいきたいと思いました。
(グッズがおしゃれでテンションが上がりました!)
<RUNTEQの入学をご検討の方・まずは詳しく話を聞いてみたいという方へ>
まずはぜひ無料のキャリア相談会へお越しください!
RUNTEQに関するご質問はもちろん、転職活動やスキルアップをする上でのご不安やお悩みも大歓迎です。
カウンセラーと一度話すことで見えてくるキャリアの道もあるかと思います。
ご興味がある方は、ぜひ下記より気軽にお申し込みをお待ちしております!