מה קלוד חשב שהוא יודע על 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. שברו את הקוד בכוונה כדי לראות אם הוא באמת עוצר את ההתנהגות שאתם רוצים לחסום.

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