Kaigi on Rails 2024 Day1
Kaigi on Rails 2024 Day1
基調講演
Rails way は哲学
おまかせは完全じゃない
その隙間を埋めると歪んでしまう
ある程度までは構造を提供するのだがその先
Rails を拡張する
他のものと混ぜ合わせるのではない
既存のコード内から抽出して抽象化する
全ての抽象化にはベースクラスが必要
Railsの仕組みを理解してモデルを上手に育てる - モデルを見つける、モデルを分割する良いタイミング
Railsの仕組みを理解してモデルを上手に育てる - モデルを見つける、モデルを分割する良いタイミング - | Kaigi on Rails 2024
https://speakerdeck.com/igaiga/kaigionrails2024
モデルの見つけ方
メインとなるテーブル名を名詞で出す
誰が・何を
イベント型モデル
名詞であるモデル名に「〜する」
複数モデルで迷った場合に捗る
複数のモデルにまたがる処理
Rails way に乗っているので楽ちん
PORO
何も継承していない。テーブルと結びついていない
まずイベント型モデルを探すこと。 テーブルに保存しなくても良いが、モデルっぽいオブジェクトを発見した時
app/models 以下におく ビジネスロジックですよ〜〜〜
命名
返ってくるオブジェクトの名前を名詞でつける
Service 層を入れるのはおすすめしない
Rails は層を減らして高い生産性を得ている
登場人物が少ない
モデルを分割する良いタイミング
コード行数が多すぎるは気にしない
そのまま書き続けるとしんどくなる時 and そのタイミングで良い分割方法がある時 -> しんどい、というのも人によるからむずい :memo:
例
モデルとフォームのバリデーションは最初は共有されている
DB と違う検証をしたい時はフォームオブジェクト
タイミングまとめ
バリデーションを条件分岐したくなった時
アプリ初期で分割してしまうと共有のメリットが得られなくなる
フォームオブジェクトのつくりかた
ActiveModel::Attributes
- 型を指定した attributes を作れる
ActiveModel::Model
ActiveModel::Model
= ActiveModel::API
+ ActiveModel::Access
そのカラム追加、ちょっと待って!カラム追加で増えるActiveRecordのメモリサイズ、イメージできますか?
そのカラム追加、ちょっと待って!カラム追加で増えるActiveRecordのメモリサイズ、イメージできますか? | Kaigi on Rails 2024
AR instance ってどれくらいメモリ使ってるんだろなっと
add_column
するとどのくらい増えるのか 224 bytes
PK + timestamps の AR instance でも 3.4KB くらいかー
4つのオブジェクトが増えている。ActiveModel::Attribute::FromDatabaseはDBからの結果をラップしている。typeを持っていて型変換もする
Sidekiqで実現する長時間非同期処理の中断と再開
Sidekiqで実現する長時間非同期処理の中断と再開 | Kaigi on Rails 2024
非同期処理の中断と再開、世間一般に意外と知見がないかもしれない
長時間のジョブが抱える課題
それを停止するの怖い
- 進捗を保存しながら処理を進行
- 全て処理終了
- 中断処理
- 再起動
- 再開処理
中断処理
設定ファイルにイベントハンドリングを設定
処理終了と停止を検知したらフラグをあげる
Sidekiq の停止を検知したら例外を送出する
再開処理
中断した箇所から処理を継続する
行番号保持方式
停止・再開のための情報を Redis に保存する
CSV のインポートなどに使われる。1行に複数のエラーが発生したりするから大変よね
ユースケース別実装パターン
- 実行時間短い&ファイル容量が小さい
- 処理が冪等なので中断処理のみでおk
- 実行時間長い&ファイル容量が大きい
- 数時間以上
- 数百MB
- デプロイに影響
- ユーザーへの業務影響が大きい
- 中断時に大きいファイルをどこに保存する?
保存先
- Redis
- メモリ容量を超える危険性
- オブジェクトストレージ GCS
- 容量が大きくても保存できる
- 暗号化やセキュリティもおk
中断・再開処理のテスト
再開の時 worker.perform を2回呼び出すことによって再開処理を再現する
Sidekiq Iteration
まだベータだがある
リリース8年目のサービスの1800個のERBファイルをViewComponentに移行した方法とその結果
リリース8年目のサービスの1800個のERBファイルをViewComponentに移行した方法とその結果 | Kaigi on Rails 2024
- パラメータ定義の曖昧さ
- 仕様に従って使うべきだがコードベースにそれらはない
- 一貫性のないパラメータの渡し方
- インスタンス変数でもローカル変数でも渡せる
ViewComponent
React インスパイアかどうかはワイはわからん
テストは erb でもかけるんだなあ
置き換えするためにパースして抽象構文木にした上で erb の render メソッドを探す
ViewComponent では content が予約されているのか
- 別系統の生成
- app/views2
- こちらが ViewComponent を使用した別系統
- view_path の分岐
prepend_viewpath を使って view_path の依存関係の一番トップに持ってくる
- コンポーネント呼び出しのインターフェースがわかりやすい
- コードジャンプがしやすい
- View のテストが可能になり、実装ミスに気づきやすくなった
Rails APIモードのためのシンプルで効果的なCSRF対策
Rails APIモードのためのシンプルで効果的なCSRF対策 | Kaigi on Rails 2024
Cookie が自動送信されることに起因する
Rails での対策
CSRF token を発行する
Rails way に乗っかる場合は View, Controller の数行で終わる
Rails API + SPA
トークン送受を自前で書くことになる
もっとシンプルに対策できないか?標準機能に引っ張られないように
- 許可したサイトからのリクエストのみ受け付ける
- Cookie が自動で送られないようにする
実際の対策
- リクエストの出所を確認
- origin header の確認
- Form POST でオリジンが送られなかった時代もあった
- 現在では全てのブラウザで対応済み
- Featch metadata
- Sec-FetchSite
- リクエスト発生元と先の関係性
- Samesite
- Lax or Strict を指定する
現実のRuby/Railsアップグレード
現実のRuby/Railsアップグレード | Kaigi on Rails 2024
当時の課題
テストカバレッジ0%
- テストを書く
- まあそうですよね
- テストをパスしないとレビューに進めないようにする
- エラーを通知する仕組みづくり
- 非推奨警告をなくす
- upgrade 作業は問題発生リスクがある
- ビジネス側との信頼関係を構築しておく
- ここまでやってようやくアップグレード
- Rails ごとにサポートしている Ruby のバージョンを確認する
rails app:update
は基本的に上書き
保守されていない gem
つら。。。
Rails をモンキーパッチしている gem
一見標準ぽいインターフェースでオーバーライドしているものは辛いな
Ruby の非互換な変更
sprockets から propshaft
Propshaft
アセットファイルを扱うことに集中する
JavaScript build は sprockets から独立させる -> build 時間を2分から2秒
CSS のプリコンパイルも独立させる
業務領域に対する理解って大切よね
賢そうなコードを書かない -> はい。。。
エンジニアの説明責任
Hotwire or React? 〜Reactの録画機能をHotwireに置き換えて得られた知見〜
Hotwire or React? 〜Reactの録画機能をHotwireに置き換えて得られた知見〜 | Kaigi on Rails 2024
- RoR / 部分的に React で SPA
React は本当に必要? -> あるある
Stimulus で実装していったが。。。ゴリゴリにJavaScript を書くことになった。じゃあ React でいいか。。。
Hotwire ならゴリゴリ JS を書かずに済みそう
「紙芝居」のように画面を切り替える
Hotwireで実装できそうか? -> 実装を CRUD に集中できそうか?