Apa yang Claude Pikir Dia Ketahui Tentang Rails Callbacks

Saya mencoba menjalankan rake task untuk menghapus record LineItem dan file S3-nya. Saya ingin menghindari callback yang berat pada model induk seperti Order.

Saya meminta bantuan Claude. Ia memberikan jawaban yang sangat meyakinkan. Ternyata, jawabannya salah.

Inilah yang saya pelajari tentang Rails, counter cache, dan mengapa Anda harus memverifikasi saran dari AI.

Problemnya LineItem belongs to OrderItem. OrderItem belongs to Order. Keduanya menggunakan counter_cache dan touch. Menghapus LineItem memicu sebuah cascade. Cascade ini menjalankan job yang berat seperti estimasi pengiriman dan kalkulasi ulang total. Saya perlu menghentikan cascade ini untuk menghemat penggunaan CPU dan biaya S3.

Kesalahan AI Claude menyarankan penggunaan skip_callback. Ini adalah ide yang buruk. skip_callback mengubah class secara global. Hal ini memengaruhi setiap thread di aplikasi Anda. Jika kode Anda crash sebelum Anda mengaktifkannya kembali, callback Anda akan mati selamanya.

Saya kemudian mencoba no_touching. Saya membungkus pemanggilan tersebut di OrderItem dan Order agar lebih aman. Tesnya berhasil, tetapi konsol menunjukkan hal yang berbeda. Timestamp Order tetap berubah.

Alasan Sebenarnya Masalahnya terletak pada bagaimana counter_cache bekerja dengan touch.

  • Saat Anda menggunakan counter_cache: true dan touch: true secara bersamaan, Rails menggabungkannya.
  • Ia menjalankan satu perintah raw SQL UPDATE ALL.
  • Raw SQL melewati lifecycle ActiveRecord.
  • Karena melewati lifecycle tersebut, hook after_commit tidak dijalankan.

Ini menciptakan paradoks yang aneh:

  • Callback OrderItem tidak berjalan karena penggabungan raw SQL tersebut.
  • Callback Order TETAP berjalan karena langkah berikutnya dalam rantai tersebut adalah touch biasa.

Solusinya Saya hanya perlu membungkus grandparent dengan no_touching.

Order.no_touching { line_item.destroy! }

Ini menghentikan touch pada level AR agar tidak mencapai model Order. Ini tidak menghentikan raw SQL pada OrderItem, tetapi itu tidak masalah karena penggabungan counter cache sudah melewati callback tersebut.

Pelajaran Utama

  • counter_cache: true + touch: true = raw SQL UPDATE ALL.
  • Raw SQL melewati semua hook after_commit.
  • touch biasa (tanpa counter cache) mengikuti lifecycle AR standar dan menjalankan callback.
  • Jangan pernah percaya kode AI secara membabi buta. Claude ingin memberikan Anda jawaban. Ia tidak peduli jika jawaban tersebut adalah halusinasi.

Selalu uji asumsi Anda di Rails console. Sengaja buat kode tersebut error untuk melihat apakah ia benar-benar menghentikan perilaku yang ingin Anda blokir.

Source: https://dev.to/husteadrobert/what-claude-thought-he-knew-about-rails-callbacks-and-how-console-testing-proved-him-wrong-j20

Optional learning community: https://t.me/GyaanSetuAi