Best practices לעבודה עם צד לקוח בריילס

הקדמה – למה כדאי לכם להמשיך לקרוא גם אם אתם לא מתכנתי רובי און ריילס

אמנם הפוסט הזה הולך לדבר על Best Practices דרך דוגמאות בריילס, אבל בהחלט אפשר לקחת את ה-Best Practices האלה וליישם אותם על כל אחת מהטכנולוגיות האחרות שאתם עובדים איתן, בין אם אתם עובדים ב-Php או אפילו דוט נט, אפשר ליישם את הפתרונות האלה בקלות יחסית.

סדר וארגון מביאים ליעילות ולכן, לחסכון בכסף ובזמן

בליבה של רובי און ריילס יש לנו את MVC, שמכריחה את המפתח (אלא אם הוא עקשן מאוד) לעבוד בצורה נכונה ולארגן את קוד צד השרת שלו למקומות הנכונים, להשתמש ב-Helpers וכן הלאה.

אם אתם מתכנתי Web סביר מאוד להניח שיש לכם עשרות, אם לא מאות, ואם לא אלפים שורות קוד לכתוב ב-JavaScript וב-Css. סביר גם להניח שיש לכם מספר גדול מאוד של קבצים לעבוד איתם.

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

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

ארגון CSS צריך להיות מבוסס על Controllers

התמונה למטה, מראה רשימת Controllers טיפוסית בפרויקט תו"כ פיתוח.

רשימת Controller בפרויקט

רשימת Controller בפרויקט

קונטרולרים בפרויקט בדרך כלל נותנים לנו מושג מעולה איך פרויקט בנוי, ולכן אני משתמש ברשימת הקונטרולרים בשביל לארגן את קבצי ה-Css שלי.

אבל ראשית, יש לי כמובן קובץ Css ראשי אחד, שבו יש את כול החוקים שהם משותפים לכול האתר, לקובץ ה-Css הזה אני בד"כ קורא main.css (מיד נראה איך הכול מאורגן בתיקיות כמובן).

להלן ספריית ה-Css שלי בהתבססות על הקונטרולרים. שימו לב לדבר אחד, אני משתמש ב-Compass וב-Scss בשביל לכתוב את הקוד, ולכן הקבצים הם לא רגילים. כמו כן, כאן הקובץ הראשי שלי נקרא dashboard.css מכיוון שהפרויקט הוא אפליקציה ולא אתר.

קבצי Css

קבצי Css

שימו לב לדבר נוסף, הקלאס הראשי בתוך הקובץ הוא בשם הקובץ שלי ולכן בשם הלוגי של המקום שבו הוא נמצא.

שימוש בקלאס ראשי לארגון התוכן הפנימי של הדף

אם נסתכל על הקובץ Layout הראשי שלי, אנחנו יכולים לראות איפה אני משתמש בקלאס הזה

	<body class="<%= controller_classes.join(' ') %>">
		<div class="wrapper">
			<div class="header <%= yield(:header_class)%>">
	    		<%= yield(:upper_links) %>
		   		<%= yield(:dashboard_header) %>
				<%= yield(:top_button) %>
		    </div><!--/header-->
		    <div class="content">
				<%= yield %>
		    </div><!--/content-->
			<%= yield(:new_issue) %>
		</div><!--/wrapper-->
		<div class="footer">
			<%= render :partial => "shared/dashboard/footer" %>
		</div><!-- .footer -->

		<%- flash.each do |name, msg| -%>
			<div id="flash_message" class="flash <%=name%>">
				<strong>
					<%= msg %>
				</strong>
			</div>
      	<%- end -%>
	</body>

שימו לב לקלאס של ה-Body הוא נלקח מקוד ומשם הוא קובע את ה-Class של כל עמוד בנפרד. כך למשל, אם יש חלקים שצריכים להראות שונה בין עמוד לעמוד, מאוד קל לבצע את זה.

את ה- controller_classes אני קובע דרך ה- application_helper בצורה הבאה:

module ApplicationHelper
  def controller_classes
    [controller.controller_name]
  end
end

למה זה מערך?

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

עכשיו, אתם בטח תוהים איך אני לוקח את כול קבצי ה-Css האלה. העוקצנים שבינכם בטח כבר חשבו למה אני טוען Css בכול עמוד בנפרד במקום קובץ אחד ויחיד שהוא Minified. ובכן, לא כך המצב. אני אכן טוען את כול הקבצים לתוך קובץ אחד ויחיד (ב-Production) שהוא Minified וגם gzipped.

אני מבצע את הדבר הזה דרך Gem שנקרא Jammit שעושה בדיוק את זה, הGem משתמש בקובץ Yaml בשביל לאחד את הקבצים, היופי ב-Gem הזה שבזמן פיתוח הוא נותן לי את כול הקבצים בצורת המקורית (אחרי ש-Compass עשה מהם Css רגיל), ובזמן Production מוגש קובץ אחד ויחיד.

אפשרות נוספת היא לעשות שימוש ב-Import של Sass, במקרה הזה הקבצים צריכים להתחיל עם Underscore ופשוט לייבא את כולם לתוך קובץ יחיד שנקרא לו application.scss או כל שם אחר שבא לכם.

דוגמא ל-Jammit Asset file

stylesheets:
  base:
    - public/stylesheets/base/all.css
    - public/stylesheets/base/form.css

ארגון קבצי JavaScript

ארגון קבצי ה-JavaScript דומה להחריד לארגון קבצי ה-Css, אלא שבמקרה הזה, אני טוען שני קבצים לתוך ה-Html.

הקובץ הראשון הוא הקובץ הכללי שכולל בתוכו קוד כללי לכול העמודים (אם יש כזה), כולל את ה-Framework לבחירה (Mootools כמובן) ועוד תוספים כאלה ואחרים.

להלן דוגמא:

javascripts:
  base:
    - public/javascripts/base/mootools-core-1.3.js
    - public/javascripts/base/mootools-more.js
    - public/javascripts/base/rails.js
  dashboard_base:
      - public/javascripts/base/flash_hanler.js
      - public/javascripts/base/scroller_bar.js
      - public/javascripts/base/behavior.js
      - public/javascripts/base/custom_select.js
      - public/javascripts/base/custom_checkbox.js
      - public/javascripts/base/paging_list.js
      - public/javascripts/base/new_project.js
      - public/javascripts/base/project.js
      - public/javascripts/modules/project/newIssue.js
      - public/javascripts/base/main.js

כפי שניתן לראות, יש כמות גדולה יותר של קבצים שנטענים בהתחלה, כמובן שכולם מאוחדים לתוך קובץ אחד ויחיד בזמן Production ומוגשים minified וgzipped.

בנוסף, לכול אחד מה-controllers יש קובץ משלו. למשל home.js, user.js ועוד.

את הקובץ הזה אני טוען בתחתית העמוד מיד אחרי קובץ הBase בצורה הבאה:

<%= javascript_include_tag "/javascripts/views/#{controller.controller_name}.js" %>

האתר שלי הרבה יותר עשיר בJavaScript, רעיון לשיפור?

בהחלט, כרגע אנחנו עובדים ב-controller scope, אפשר בהחלט לעבוד ב-view scope ולייצר קבצים (גם Js וגם Css) לכול אחד מה-Views שלכם ול-Partials.

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

הערת שוליים קטנה או => נראה לכם באמת שאני עובד ככה…

אתם בטח חושבים לעצמכם, אין מצב, זה נראה יותר מדי עבודה, לך תזכור להוסיף את הקבצים במקום ולך תזכור לטעון אותם וכהנה וכהנה הערות. ובכן, אחד הדברים ששברו אותי בתחילה כאשר התחלתי עם השיטה הזו אכן היה הנושא של הניהול, בעיקר ביצירת הקבצים וניהול של ה-Minify והטעינה לתוך Jammit

מי אמר Rails Custom Generators?

בדיוק בשביל זה יש לי Custom Generator ובמקום ליצור Controller דרך הקומנד ליין הרגיל, אני יוצר אותו דרך Custom Command שבעצם עושה את כול הדברים בשבילי.

  • יצירת Controller
  • יצירת קובץ Scss
  • הוספה של הקובץ לסדר הMinify (פרמטר אופציונאלי האם הוא בייס או לא)
  • הוספה של קובץ Js
  • הוספה של הקובץ לסדר הMinify (פרמטר אופציונאלי האם הוא בייס או לא)

לסיכום

אשמח לשמוע תגובות, הערות, הארות (אני פתוח לכול ביקורת חיובית :-) )

לייקים בפייסבוק וגם תגובות דרך הפייסבוק יתקבלו גם הן בברכה.

בהצלחה!

כתיבת תגובה

האימייל לא יוצג באתר. (*) שדות חובה מסומנים

*

תגי HTML מותרים: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>