בסוף זה תמיד הטיפול בשגיאות
מצאתי השבוע באג מעניין פה באתר בפונקציה שתמיד נראתה לי כמו קסם. הסיפור הוא פשוט, לפעמים אנשים קונים מנוי לאתר עבור עובדים שלהם ואז העובד מקבל קישור מיוחד להרשמה. כשהעובד נרשם דרך הקישור הוא מחובר לאותו חשבון חברה שכבר נקנה עבורו במרוכז ויכול לגשת לקורסים. הקוד שטיפל ביצירת בחיבור העובד לקוד המיוחד הוא בסך הכל השורות:
create_user(!!params[:quickjoin]) do |user|
user.after_confirmation
end
נו, למעשה המימוש נמצא בתוך הבלוק after_confirmation
אבל זה לא חשוב לשיחה שלנו כרגע. ועכשיו שאני קורא את זה אני גם לא בטוח מה תפקיד הפרמטר quickjoin, אבל גם זה לא חשוב לשיחה שלנו כרגע.
מה שכן חשוב וקצת קשה לראות מהמבנה זה ש create_user
יכולה להיכשל. למשל אם מישהו בחר אימייל שכבר קיים במערכת, לא בחר סיסמה או לא בחר שם משתמש. במצב כזה הבלוק הפנימי לא נקרא וזה ברור כי לא נוצר משתמש. הקוד שמופעל אחרי כישלון ביצירת משתמש מתחבא בתוך הפונקציה create_user
והוא השורות:
clean_up_passwords resource
set_minimum_password_length
return redirect_to quickjoin_path, alert: resource.errors.full_messages.join(', ') if params[:quickjoin] == '1'
respond_with resource
בפרט מה שמעניין אותנו זו השורה האחרונה - respond_with
. היא מעניינת כי היא עובדת ממש בסדר לכל המשתמשים שנרשמים רגיל לאתר. כשיש כישלון ברישום היא מחזירה את הנרשם לדף הרישום הראשי שם הוא יכול לתקן את השגיאה ברישום ולנסות שוב. אבל אם מראש הקישור לרישום היה שונה כי הבן אדם הגיע מתוך קישור מיוחד כדי להשתמש בחשבון מתנה, הפונקציה respond_with
לא רואה את זה ומחזירה את הנרשם לדף הרישום הראשי, שם הוא מנסה שוב להירשם אבל החשבון כבר לא מחובר לחשבון שקנו עבורו.
ב Rails הפונקציה respond_with
היא קיצור לזה:
def create
@user = User.new(params[:user])
respond_to do |format|
if @user.save
flash[:notice] = 'User was successfully created.'
format.html { redirect_to(@user) }
format.xml { render xml: @user }
else
format.html { render action: "new" }
format.xml { render xml: @user }
end
end
end
בכתיב המלא הכל ברור - כשיצירת המשתמש נכשלה מציגים את הטופס מ new, ולא מהקישור המיוחד דרכו הוא ניסה להירשם. ברישום הבא המשתמש כבר ייכנס לאתר כמשתמש רגיל ולא מחובר לחשבון שהוכן עבורו.
תיקונים? קל. קודם כל ב create_user
עדיף להחליף את respond_with
בגירסה הארוכה שלה, ואז בכישלון גם להפעיל redirect לקישור ממנו הוא ניסה להירשם. בנוסף להוסיף בדיקות צד-לקוח בטופס הרישום. בדיקות אלה אומנם לא יתפסו את כל הבעיות אבל ישפרו את החוויה למי ששכח למלא תוכן באחד השדות.