ניתובים דינאמיים עם סינטרה

אם אתם עדיין לא מכירים את סינטרה, אז דבר ראשון תתבישו לכם, ודבר שני איפה אתם חיים ? זה הmicro-framework המדובר ביותר בשנתיים האחרונות, ויש כל כך הרבה ניסיונות לממש אותו בעוד שפות, אבל הוא פשוט תפור על רובי כמו כפפה ליד.

בדוגמא הראשונה שהעברתי על סינטרה, העתקתי דוגמא סטטית מאוד, על קוד אשר מאוד ברור מה קורה איתו. אבל מה קורה כאשר החוקים שלנו זהים תמיד בניתוב, אבל אנחנו צריכים משהו יותר דינאמי ? הרי אם יש לי עכשיו 20 דפים, כאשר חוקי הניתוב זהים לחלוטין, 20 חוקים זה יותר מידי, אז אם אתם נמצאים במצב הזה, הפוסט הזה בשבילכם.

נתחיל בדוגמא פשוטה: אני רוצה שכל דף אשר מתקבל ללא חוק מסויים שקבעתי, אלא ב "root" הראשי של האתר, יפונה לכתובת נכונה יותר. אני אבצע את זה בצורה הבאה:

get '/:page' do |page|
 redirect home_path(lang) unless PAGES.include? page
 redirect send :"#{page}_path", lang 
end

לקוח מאפליקציה אמיתית שיש אצלי בסינטרה. מה שקורה כאן הוא מאוד פשוט אני יצרתי ניתוב עם משתנה פשוט, אשר קראתי לו page. הנקודותיים אומרות לסינטרה שמדובר במשתנה, ולא בשם "קבוע". אל תוך הבלוק, קיבלתי את המשתנה (בין הpipes), ונכנסתי לממש את הבלוק. שם אני שואל האם בקבוע שהגדרתי מראש עם שמות כל הדפים שלנו, האם הדף קיים. במידה ולא אז אני מפנה לניתוב הבית שלנו (אני לא רוצה דף 404, למרות שגם זה אפשרי כאן). במידה והדף קיים, אני משתמש בhelper אחר שיצרתי בשם lang וקורא בצורה דינאמית לדף עם ה helper של הניתוב השייך אליו.

פרט חשוב כאשר עובדים עם send ברובי. זו פונקציה מאוד מסוכנת, היות והיא מריצה בצורה דינאמית כל מתודה שמעבירים לה. לכן אם לא רוצים בעיות אבטחת מידע, מומלץ מאוד להשתמש בסניטציה כלשהי על התוכן במשתנה שמעבירים לה, למשל בצורה שאני עשיתי כאן, או בדרכים אחרות.

מה שעשיתי כאן, מתאים אומנם למקרה בודד בו אני מקבל דף, אבל המבנה של הניתוב שלי הוא של שפה ואז שם הדף שאני מעוניין לקבל. העניין הוא שאני רוצה להגביל שהנתיב של שפה תמיד יהיה 2 תווים בלבד, והשם של הדף לא מוגבל. כאן כבר צריך חוק יותר גמיש, והחוק למעלה לא מסוגל להתמודד עם גישה כזו, אבל החוק הבא כן:

get %r!^/([a-z]{2})/([a-zA-Z0-9_]+)$! do |alang, page|
  alang = lang unless LANGS.include? alang
  redirect home_path(alang) unless PAGES.include? page
  # ...
end

הפעולה שנעשת כאן משתמשת בRegular Expression או regex בקיצור. ברובי, כמו בפרל, אפשר לשנות את המבנה ברירת המחדל של regex, כאשר המבנה הרגיל יגרור לנו כאב ראש. כאן החלפתי את הלוכסן המוכר בסימן קריאה, בשביל התחלה וסיום החוק, היות והסימן קריאה אינו נמצא אצלנו בשימוש בחוק, בעוד שהלוכסן דווקא כן. אני אומר בחוק שההתחלה של הנתיב מתחילה בלוכסן, ואז מכילה 2 תווים, כאשר 2 התווים יהיו בקבוצה 1. 2 התווים מופרדים עם עוד לוכסן, ואז יש שם שיכול להיות עם אותיות קטנות, גדולות, מספרים וקו תחתי, וחוזר מספר פעמים לא ידוע מראש עד שמסתיים, ומכניס אותם לקבוצה מספר 2.

את 2 הקבוצות אני מכניס למשתנים בבלוק בשם alang לקבוצה הראשונה, והקבוצה השניה תהיה במשתנה שנקרא page. כאן החוק הראשון והשני בבלוק מבצעים סניטציה על המידע שקיבלנו. לא מספיק שנכנסנו לבלוק כאשר הregex מתאים אלא אנחנו קובעים במדוייק האם המידע שקיבלנו מקובל עלינו, ורק אם כן, אנחנו מבצעים את מה שצריך.

במידה אבל ש2 החוקים שלנו לא יכולים להתקיים, אנחנו רוצים לשלוט באיך שדף ה404 שלנו יעבוד. בשל כך אנחנו נשתמש בבלוק טבעי של סינטרה:

not_found do
  # ...
end

וזה הכל להפעם.

כתיבת תגובה

הזינו את פרטיכם בטופס, או לחצו על אחד מהאייקונים כדי להשתמש בחשבון קיים:

הלוגו של WordPress.com

אתה מגיב באמצעות חשבון WordPress.com שלך. לצאת מהמערכת / לשנות )

תמונת Twitter

אתה מגיב באמצעות חשבון Twitter שלך. לצאת מהמערכת / לשנות )

תמונת Facebook

אתה מגיב באמצעות חשבון Facebook שלך. לצאת מהמערכת / לשנות )

תמונת גוגל פלוס

אתה מגיב באמצעות חשבון Google+ שלך. לצאת מהמערכת / לשנות )

מתחבר ל-%s