מה קלוד חשב שהוא יודע על Rails callbacks
ניסיתי להריץ rake task כדי למחוק רשומות LineItem וקבצי S3 שלהם. רציתי להימנע מ-callbacks יקרים במודלים אב כמו Order.
ביקשתי עזרה מקלוד. הוא נתן תשובה בביטחון רב. הוא טעה.
הנה מה שלמדתי על Rails, counter caches, ולמה חובה לוודא את העצות של ה-AI.
הבעיה LineItem שייך ל-OrderItem. OrderItem שייך ל-Order. שניהם משתמשים ב-counter_cache וב-touch. מחיקת LineItem מפעילה שרשרת (cascade). השרשרת הזו מפעילה עבודות (jobs) כבדות כמו הערכות משלוח וחישוב מחדש של סכומים כוללים. הייתי צריך לעצור את השרשרת הזו כדי לחסוך ב-CPU ובעלויות S3.
הטעות של ה-AI קלוד הציע להשתמש ב-skip_callback. זה רעיון רע. skip_callback משנה את המחלקה (class) באופן גלובלי. זה משפיע על כל thread באפליקציה שלך. אם הקוד שלך קורס לפני שתפעיל אותו מחדש, ה-callbacks שלך יישארו כבויים.
לאחר מכן ניסיתי את no_touching. עטפתי את הקריאה גם ב-OrderItem וגם ב-Order כדי להיות בטוח. הבדיקות עברו, אבל ה-console הראה משהו אחר. ה-timestamp של ה-Order עדיין השתנה.
הסיבה האמיתית הבעיה הייתה האופן שבו counter_cache עובד עם touch.
- כשמשתמשים ב-counter_cache: true וגם ב-touch: true יחד, Rails מאחד אותם (bundles).
- הוא מריץ פקודת raw SQL אחת מסוג UPDATE ALL.
- raw SQL עוקף את ה-lifecycle של ActiveRecord.
- מכיוון שהוא עוקף את ה-lifecycle, ה-after_commit hooks לא מופעלים.
זה יצר פרדוקס מוזר:
- ה-callbacks של OrderItem לא הופעלו בגלל איחוד ה-raw SQL.
- ה-callbacks של Order כן הופעלו, כי השלב הבא בשרשרת היה touch רגיל.
הפתרון הייתי צריך רק לעטוף את ה-"סבא" (grandparent) ב-no_touching.
Order.no_touching { line_item.destroy! }
זה מונע מה-touch ברמת ה-AR להגיע למודל ה-Order. זה לא עוצר את ה-raw SQL ב-OrderItem, אבל זה לא משנה כי איחוד ה-counter cache כבר מדלג על ה-callbacks האלו.
תובנות מרכזיות
- counter_cache: true + touch: true = raw SQL UPDATE ALL.
- raw SQL מדלג על כל ה-after_commit hooks.
- touch רגיל (ללא counter cache) עוקב אחר ה-lifecycle הסטנדרטי של AR ומפעיל callbacks.
- לעולם אל תסמכו על קוד של AI באופן עיוור. קלוד רוצה לתת לכם תשובה. לא אכפת לו אם התשובה היא הזיה (hallucination).
תמיד בדקו את ההנחות שלכם ב-Rails console. שברו את הקוד בכוונה כדי לראות אם הוא באמת עוצר את ההתנהגות שאתם רוצים לחסום.
Optional learning community: https://t.me/GyaanSetuAi