• בלוג
  • perl
  • מוג'ולישס הוא הפריימוורק הכי מדליק שלא היכרתם לפיתוח צד-שרת (ויש גם דוגמת קוד להמחשה)

מוג'ולישס הוא הפריימוורק הכי מדליק שלא היכרתם לפיתוח צד-שרת (ויש גם דוגמת קוד להמחשה)

27/10/2016

לפרל יש 3 ספריות פיתוח ווב: הראשונה נקראת Catalyst והיא ממש מסובכת ומהונדסת יתר על המידה. השניה נקראת Dancer והיא דוקא מאוד פשוטה אבל עדיין לא ממש יציבה, והשלישית נקראת מוג'ולישס, ולמרות השם המוזר היא דוקא די פשוטה. בואו נראה כמה דרך דוגמא קצרה.

1. מה בונים

מכירים את cowsay כן? יישום שורת פקודה קצר שמציג איור של פרה ב Ascii Art שאומרת מה שביקשתם. כאן יש גירסת אונליין למי שלא מכיר:
http://cowsay.morecode.org/

2. ועכשיו למוג'ולישס

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

mojo generate app MyCow

השלד כולל מספר קבצים שכבר מספרים לנו איך הפריימוורק בנוי. הקובץ הראשי lib/MyCow.pm כולל קוד אתחול ואת הגדרת הנתיבים:

package MyCow;
use Mojo::Base 'Mojolicious';

# This method will run once at server start
sub startup {
  my $self = shift;

  $self->plugin('MyCow::Plugin::Cowsay');

  # Router
  my $r = $self->routes;

  # Normal route to controller
  $r->get('/')->to('example#welcome');
}

1;

קל לראות בשורה האחרונה שכל בקשת GET לנתיב / תנותב לפונקציה welcome של רכיב בשם example. מוג'ולישס לקח מריילס את ההעדפה לקונבנציות ולכן את הרכיב example נוכל למצוא בתיקיית Controller בשם Example.pm. הפונקציה welcome מוגדרת בתוך רכיב זה:

sub welcome {
  my $self = shift;

  # Render template "example/welcome.html.ep" with message
  my $text = $self->param('text') || 'Hello World';
  my $cowfile = $self->param('cowfile') || 'default';

  $self->cowsay->say($text, $cowfile);

  $self->stash(list => [map { (fileparse($_, '.cow'))[0] } $self->cowsay->list]);
  $self->stash(selected => $cowfile);
}

תפקידו של ה Controller במוג'ולישס הוא להכין את המשתנים לצורך הצגתם על המסך. אופן ההצגה הספציפי נקבע ברכיב נוסף שנקרא Template עליו נדבר מיד.

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

אוביקט זה הוא שמאפשר לגשת לפרמטרים של הבקשה באמצעות הפונקציה param שלו. שתי השורות הבאות בפונקציה שולפות פרמטרים למשתנים עם ערכי ברירת מחדל – אם הועבר ערך לפרמטר text נשתמש בו, ואם לא נשתמש בערך הקבוע Hello World.

האחריות השניה של ה Action היא לייצר את המשתנים עבור התבנית. הדרך הפשוטה ביותר לעשות זאת היא הפונקציה stash שמאחסנת את המשתנים וערכיהם. שתי השורות האחרונות ב Action מאחסנות את המשתנים selected ו list כך שיהיו זמינים לתבנית.

3. פלאגינים

עכשיו אפשר לקחת רגע ולשאול איך עובד החיבור עם יישום cowsay. שימו לב לשורה:

  $self->cowsay->say($text, $cowfile);

מהיכן הגיע המשתנה cowsay? ואיפה מוגדרת הפונקציה say? במוג'ולישס נהוג להדביק את אוביקטי הלוגיקה על אוביקט הפריימוורק וכך לאפשר גישה מהירה אליהם. אוביקטים אלו נקראים Plugins. בדרך כלל יהיה לכם פלאגין אחד דרכו תקבלו גישה לאוביקטי הלוגיקה עצמם, לדוגמא פלאגין של חיבור לבסיס הנתונים שדרכו תוכלו לעבוד עם ה DB, או פלאגין של גישה למערכת קבצים.

בתוכנית שלנו הגדרתי את הממשק עם cowsay כפלאגין באמצעות הקוד שבקובץ lib/MyCow/Plugin/Cowsay.pm. הפונקציה המרכזית בקובץ הינה:

package MyCow::Plugin::Cowsay;
use Mojo::Base 'Mojolicious::Plugin';

sub register {
  my ($self, $app) = @_;
  my $cowpath = cowspath();
  my @cows = glob("$cowpath/*.cow");

  $app->helper('cowsay.say' => sub {
    my ($c, $text, $cowfile) = @_;

    open my $fh, '-|', '/usr/local/bin/cowsay', '-f', $cowfile, $text or die $!;
    local $/;
    my $res = <$fh>;

    $c->stash(cow => $res);
  });

  $app->helper('cowsay.list' => sub {
    return @cows;
  });
}

תפקידה של פונקציית register להגדיר את הפונקציות שהפלאגין חושף (נקראות helpers). בדוגמא שלנו מדובר על הפונקציות say ו list. הפונקציה say מוסיפה משתנה ל stash והפונקציה list פשוט מחזירה את רשימת האיורים המותקנים.

4. קוד התבנית

עכשיו שהבנו איך המנגנון עובד נותר רק לראות את התבנית המייצרת את ה HTML עבור הדפדפן. למוג'ולישס יש שפת תבניות שנקראת epl, שהיא הכלאה מוזרה בין perl ל php. יש עוד שפות תבניות נתמכות אבל epl מאוד אינטואיטיבית, מאחר וכל הקוד הוא פשוט קוד פרל, וכל המשתנים מה stash זמינים כמשתנים לתבנית.

עבור הרכיב example והפונקציה welcome התבנית המתאימה היא templates/example/welcome.html.ep. מוג'ולישס משתמש בקונבנציות ולכן שם התבנית נגזר משם הרכיב והפונקציה אליהם היא מתאימה. זה הקוד בקובץ:

% layout 'default';
% title 'Welcome';
<h2>Look a cow</h2>
<form>
<input type="text" name="text" />
<select name="cowfile">
  <% for my $cow (@$list) { %>
    <% if ($cow eq $selected) { %>
      <option value="<%= $cow %>" selected><%= $cow %></option>
    <% } else { %>
      <option value="<%= $cow %>"><%= $cow %></option>
    <% } %>
  <% } %>
</select>
<input type="submit" value="Say" />
</form>

<pre><%= $cow %></pre>

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

5. הקוד בפעולה (ומסקנות)

אפשר לראות את הקוד בפעולה בקודפיקניק הבא:

בשביל להריץ כתבו את הפקודה:

./my_cow/script/my_cow daemon -l http://0.0.0.0:$BASKET_APP_PORT

לאחר מכן לחצו על אייקון כדור הארץ כדי לקבל איור של פרה, או דפדפן בקבצי הקוד בצד שמאל.

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