Apa yang Claude Sangka Dia Tahu Tentang Rails Callbacks
Saya cuba menjalankan tugasan rake untuk memadam rekod LineItem dan fail S3 berkaitan. Saya ingin mengelakkan callback yang memakan kos tinggi pada model induk seperti Order.
Saya meminta bantuan Claude. Ia memberikan jawapan yang penuh yakin. Namun, ia salah.
Inilah apa yang saya pelajari tentang Rails, counter cache, dan mengapa anda mesti mengesahkan nasihat AI.
Masalahnya
LineItem belongs to OrderItem. OrderItem belongs to Order. Kedua-duanya menggunakan counter_cache dan touch.
Memadam LineItem mencetuskan rantaian (cascade). Rantaian ini menjalankan tugasan berat seperti anggaran penghantaran dan pengiraan semula jumlah.
Saya perlu menghentikan rantaian ini untuk menjimatkan kos CPU dan S3.
Kesilapan AI
Claude mencadangkan penggunaan skip_callback.
Ini adalah idea yang buruk. skip_callback mengubah kelas secara global. Ia menjejaskan setiap thread dalam aplikasi anda. Jika kod anda terhenti (crash) sebelum anda mengaktifkannya semula, callback anda akan kekal tidak berfungsi.
Saya kemudian mencuba no_touching. Saya membungkus (wrap) panggilan tersebut dalam OrderItem dan Order untuk keselamatan.
Ujian lulus, tetapi konsol menunjukkan sesuatu yang berbeza. Cap masa (timestamp) Order masih berubah.
Sebab Sebenar
Isunya adalah bagaimana counter_cache berfungsi dengan touch.
- Apabila anda menggunakan
counter_cache: truedantouch: truebersama-sama, Rails menggabungkannya (bundles). - Ia menjalankan satu arahan raw SQL
UPDATE ALL. - Raw SQL memintas (bypasses) kitaran hayat (lifecycle) ActiveRecord.
- Kerana ia memintas kitaran hayat, hook
after_committidak akan dicetuskan.
Ini mewujudkan paradoks yang pelik:
- Callback OrderItem tidak dicetuskan disebabkan oleh gabungan raw SQL tersebut.
- Callback Order BERJAYA dicetuskan kerana langkah seterusnya dalam rantaian tersebut adalah
touchbiasa.
Penyelesaian
Saya hanya perlu membungkus grandparent dalam no_touching.
Order.no_touching { line_item.destroy! }
Ini menghalang touch pada tahap AR daripada sampai ke model Order. Ia tidak menghentikan raw SQL pada OrderItem, tetapi itu tidak menjadi masalah kerana gabungan counter cache sudah pun melangkau callback tersebut.
Pengajaran Utama
counter_cache: true+touch: true= raw SQLUPDATE ALL.- Raw SQL melangkau semua hook
after_commit. touchbiasa (tanpa counter cache) mengikut kitaran hayat AR standard dan mencetuskan callback.- Jangan sesekali mempercayai kod AI secara membuta tuli. Claude mahu memberikan anda jawapan. Ia tidak peduli jika jawapan itu adalah halusinasi.
Sentiasa uji andaian anda dalam konsol Rails. Rosakkan kod dengan sengaja untuk melihat sama ada ia benar-benar menghentikan tingkah laku yang ingin anda sekat.
Komuniti pembelajaran pilihan: https://t.me/GyaanSetuAi