361 Views
September 27, 24
スライド概要
Railsのコールバックは気をつけて使用しないと予期しない事を起こしてしまいます。こちらを事例を用いて説明させていただきます
コールバックは気をつけて使おう!! #つくてくトーク ツクリンク株式会社 ⼋尾 (@Tomoki____Y)
⾃⼰紹介 ● ● ● 名前 ○ やお ともき(@Tomoki____Y) ツクリンク株式会社 アソシエイトエンジニアリングマネージャー 経歴 ○ 2018年 異業種からエンジニアへ転⾝ ○ 2022年 ツクリンク⼊社 ○ エンジニアとして転⾝してから、ずっとメインはRailsを使⽤している
Railsのコールバックとは?
コールバックとは 補⾜: 本スライドでは、Active Recordのコールバックについて記載していきます コールバックとは、オブジェクトのライフサイクル期間における特定の瞬間に呼び出されるメ ソッドのことです。コールバックを利⽤することで、Active Recordオブジェクトが作成/保存/ 更新/削除/検証/データベースからの読み込み、などのイベント発⽣時に常に実⾏されるコード を書くことができます。 引⽤: Railsガイド ● コールバックは、ActiveRecordオブジェクトの作成‧更新などの状態が変動した時にイベン トが発⽣ ● そのイベント発⽣時に実⾏されるコードを書くことができる
ソースコード内のこういうやつ before_validation バリデーションの直前に呼び出される コールバック after_validation バリデーションの直後に呼び出される コールバック before_save レコードが保存される前に呼ばれる コールバック after_save レコードが保存された後に呼ばれる コールバック before_create レコードが作成される前に呼ばれる コールバック after_create レコードが作成された後に呼ばれる コールバック before_update レコードが更新される前に呼ばれる コールバック after_update レコードが更新された後に呼ばれる コールバック
なんで気を付ける必要がある? 気をつけないと何が起こる?
チーム開発の規模が⼤きくなってく ると結構⾟い状況になる😭😭
⾟い状況事例 太郎さんは、ある機能を作る事を依頼され、その機能はAのオブジェクト作成時 にBのオブジェクトも作成するという機能の作成を⾏うものだった。 太郎さんは、Aのオブジェクトのコールバックを使⽤してBのオブジェクトを作成 すればできるなと考え実装に移した。
実装ソースコード 太郎さんが下記のように実装した
数年後開発組織がでかくなってき‧‧‧
Aのオブジェクトのコールバック Aのオブジェクトのコールバックは下記のような状態になっていた。。
新しく次郎さんの⼊社 新しく⼊社した次郎さんは、Aのオブジェクトに関わる機能の開発を任され実装を進めていまし た。 次郎さんは、Aのオブジェクトの操作が意図通りに動かず、何回も確認するが原因がわからず、太 郎さんへ相談を⼊れました。 太郎さんが確認すると、コールバックが原因な事が分かり、次郎さんは⾒当違いな部分を何回も 確認して時間を潰す状態を引き起こしてしまいました。 💡このようにコールバックは、ソースコード上処理の連続性がないところで記述 するので、コールバック実装者以外は処理を追うのは難しい状態になります。
さらに さらに次郎さんの機能では、Aのオブジェクトのコールバックで不要な部分が存 在する事が分かり、容易に削除は出来ないので下記のようなトリッキーな実装で 対応する事になってしまいました。。😭😭
さいごに ● コールバックの実⾏は把握しづらいので、本当にコールバックにするべきか 検討して⼊れないと、予期せぬバグを招く可能性があるかつ⽣産性の低下に も繋がってしまう。 ● また、後からコールバックを外していくのは、簡単な話ではなく開発⼯数は それなりにかかる事が多いので容易に⼊れるべきではないと考えている。 ● 私は今回のスライドの経験から、まずはコールバックを使わない⽅法で考え る意識で実装するようになりました。。😭
おまけ コールバックで⾮同期処理をする際は、after_saveではなくてafter_commitで実施するように しよう! 上記の様にafter_saveで、⾮同期Jobをエンキューするとトランザクション処理中に⾮同期処理 が実⾏される可能性があります。タイミングによっては、⾮同期Jobでレコードが⾒つからず落ち る事になるので、トランザクションが閉じた後のafter_commitで実⾏するのが適切です。
ご清聴ありがとうございました! #つくてくトーク