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: truedantouch: truesecara bersamaan, Rails menggabungkannya. - Ia menjalankan satu perintah raw SQL
UPDATE ALL. - Raw SQL melewati lifecycle ActiveRecord.
- Karena melewati lifecycle tersebut, hook
after_committidak dijalankan.
Ini menciptakan paradoks yang aneh:
- Callback
OrderItemtidak berjalan karena penggabungan raw SQL tersebut. - Callback
OrderTETAP berjalan karena langkah berikutnya dalam rantai tersebut adalahtouchbiasa.
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 SQLUPDATE ALL.- Raw SQL melewati semua hook
after_commit. touchbiasa (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.
Optional learning community: https://t.me/GyaanSetuAi