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 (פרמטר אופציונאלי האם הוא בייס או לא)

לסיכום

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

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

בהצלחה!

אתר מאפס ברובי און ריילס #3 (סקרינקאסט)

החלק השלישי בסדרה, בחלק זה אני עובר על יצירת מודלים לנתונים, יצירת מבחנים למודלים האלה ועל קשרים בין מודלים ב-ActiveRecord.

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

תהנו,
כרגיל, אשמח לתגובות ולייקים.

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

Creating a rails application from scratch #3 from Avi Tzurel on Vimeo.

כמובן כרגיל, קוד המקור נמצא ב-Github ואתם יכולים לשכפל אותו ולעשות איתו כרצונכם, השימוש הוא חופשי לגמרי.
https://github.com/KensoDev/Adopt-A-Cause

מוזיקת הפתיח מאת http://www.danosongs.com/

לקוח חדש – GogoBot

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

הסרטון הבא יסביר בקצרה על חברת GogoBot – מה הם עושים, צוות העובדים ועוד.

הנה הסבר מטעם מנכ"ל החברה ואחד המייסדים, טרוויס כץ.

העבודה שלי

  • פיתוח רובי און ריילס
  • פיתוח אלגוריתם להשוואת בסיסי נתונים
  • פיתוח צד לקוח

אתר מאפס ברובי און ריילס #2 (סקרינקאסט)

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

זהו החלק השני בסדרה, שבו הוספנו את מודל ה-User כולל את האפשרות שמשתמשים יבצעו Login, Forgot Password ועוד.

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

אשמח לתגובות (גם דרך הפייסבוק) וכרגיל לייקים יתקבלו בברכה גם כן.

תהנו!

Creating a rails application from scratch #2 from Avi Tzurel on Vimeo.

אתר מאפס ברובי און ריילס #1 (סקרינקאסט)

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

Creating a rails application from scratch (pt 1) from Avi Tzurel on Vimeo.

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

בחלק האחרון של הסרטון יצרנו את ה-Title המתאים לעמוד ה-Index בController => Home.

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

בסרטונים הבאים, נמשיך וניצור את האתר כמובטח.

קישורים מהסרטון:

https://github.com/ryanb/nifty-generators
http://rspec.info/
https://github.com/thoughtbot/factory_girl
http://gembundler.com/

נשמח לתגובות, לייקים ושיתופים.

איך תורמים לשתי קהילות במקביל עם רובי און ריילס?

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

על המיזם החברתי

dollar and Donation Box
המיזם הוא אתר אינטרנט. האתר יאפשר לכול מי שרוצה לגייס כסף לכול מטרה לעשות זאת בקלות.

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

לכן, החלטתי להקים את אתר "אמץ מטרה" (השם זמני). האתר יאפשר לכול מי שחפץ לפתוח "מטרה", אנשים מהישוב יוכלו להכנס לאתר, לבחור להם מטרה ולתרום לה כסף או לאמץ אותה.

אימוץ מטרה אומר למשל שאני בוחר לשלם כול חודש 150 שקלים לטובת משפחת XYZ מישוב YZF. בכך בעצם אני דואג להכנסה קבועה למשפחה מכמה תורמים.

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

כול מי שתורם יוכל (אם ירצה) לפרסם את התרומה שלו על ה-Wall בפייסבוק ובכך להפיץ את השמועה ולעזור למטרה שהוא בחר בכך שגם החברים שלו יעזרו לאותה המטרה.

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

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

רגע? אין אתרים כאלו?

אז כן, יש כאלו אתרים – בעולם יש כאלה כמו pledgie.com ואפילו Facebook Causes, אבל הם לא חשופים לקהל הישראלי שלטובתו אני מרים את האתר הזה, לא תמיד גם האנשים שזקוקים לעזרה יודעים אנגלית ולכן אני רוצה להנגיש את האתר בצורה הכי גבוהה שאפשר.

אודות האתר

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

צילומי מסך מה-Mockups

דף פנימי - מטרה, תורמים, שיתוף

דף פנימי - מטרה, תורמים, שיתוף

כניסה לאתר, גם דרך פייסבוק וטוויטר

כניסה לאתר, גם דרך פייסבוק וטוויטר

מה זה קשור לריילס ואיך זה תורם לשתי קהילות?

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

יהיה קוד פתוח?

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

השאיפה שלי היא ליצור בכול שבוע סרטון של שעה-שעה וחצי ובכך לייצר התקדמות טובה מאוד ולהרים אתר לאוויר בתקופה יחסית קצרה.

מה אנחנו צריכים מכם?

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

שיהיה לכולנו בהצלחה!

החלק הראשון

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

לינקים שימושיים למפתחים #1

פוסט ראשון בסדרה, בפוסטים האלה אני אפרסם לינקים שימושיים למפתחים (בעיקר למפתחי רובי און ריילס ומפתחי Web)

iAd Producer – למי שרוצה לקחת חלק ולפרסם iAds ברשת של אפל, אפל הוציאו Producer מיוחד שמאפשר ליצור מודעות כאלה בצורה של Wysiwyg והפלט של העורך הזה הוא Html5 וCss3 שכול המכשירים של אפל יודעים לקרוא, בינהם הiPhone וכמובן הiPad.

Tower – אני משתמש במק, מאז שאני משתמש במק אני משתמש לSource Control ב-Git כמעט באופן בלעדי (מלבד פרויקט או שניים שקיבלתי בירושה). הרבה זמן השימוש ב-Git הרגיש לינוקסאי מדי, יותר מדי Command שקשה מאוד לזכור את קובן אבל החלק שבאמת היה לי קשה עם Git הוא לעשות Diff, לראות היסטוריה וכדומה.
בדיוק כאן נכנסת לתמונה האפליקציה המעולה הזו, אני משתמש בה באופן קבוע בשביל לראות היסטוריה של Commits, לשחזר קטעי קוד ולעשות Merge בין ענפים)

צילום מסך Git Tower

צילום מסך Git Tower

סיור באתר באמצעות jQuery – אמנם לאחרונה אני עושה שימוש בMootools בכול הפרויקטים החדשים שלי אבל זה Tutorial נחמד שמראה איך אפשר ליצור סיור באתר ולהניח Tooltips במקומות הנכונים עם הסבר של מה בדיוק החלק הזה עושה. לאפליקציות עם אינטראקציה רבה זה בהחלט יכול להיות מאוד שימושי.

סיור וירטואלי באתר

סיור וירטואלי באתר

5 דברים שלא ידעתם על jQuery – שוב, אם אתם עושים שימוש ב-jQuery יש כאן אוסף של 5 דברים עם אוסף של קטעי קוד מאוד שימושיים, אני יכול לומר שתור משתמש jQuery לשעבר שחלק מהדברים גם חידשו לי קצת.

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

MongoDB Gotchas - אם אתם משתמשים בריילס וב-MongoDB יש כאן טיפים יקרים מפז.

25 טיפים לVim – אוסף של 25 טיפים בין אם כפוסטים בבלוג או כסקרינקאסטים (שאני מאוד אוהב) לשימוש בVim.

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

שורפות לי העיניים ואפשר להאשים רק את באג

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

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

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

הווה אומר, אני מבלה שעות רבות מול המחשב בכול יום, אמנם יש לי מסכים איכותיים ומחשבים איכותיים אבל עדיין מדובר במאמץ די גדול על העיניים.

עד כאן ההקדמה, אפשר להמשיך?

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

יצאתי מהחנות עם משקפיים, שמח וטוב לב.

ד.א, המחיר הוא בערך 450 שקלים.

רגע רגע, משפטים לא צפויים בדרך…

מה אומר לכם חברים, הייתי מאוד מרוצה מהמשקפיים, מאוד!

המשקפיים מסירות המון מאמץ מהעיניים ואני הייתי (ותיכף אסביר למה זה בלשון עבר) מסיים ימים שלמים של פיתוח תוכנה ללא כאבי עיניים.

1-12-2011 6-25-32 PM

עד כאן, דברים טובים (אבל באמת, מוצר מעולה… שיהיה ברור)

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

רגע רגע, כן כן, אתם שומעים נכון, אני אשם שהמשקפיים נשברו ולוקח אחריות על כך.

יופי, נמשיך

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

גילוי יותר מנאות

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

הוא אמר לי שהוא מאוד מעריך את הכנות שלי ושבכול מקרה זה באחריות והוא יטפל בזה.

סיכמנו שאשאיר את המשקפיים בחנות בקריון והוא יגיע לשם ויטפל בהן.

אחחח… דרכי הייסורים של השירות בבאג

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

כן כן, מגיע פיזית לחנות ושואל על המשקפיים את המוכרים שם, בכול פעם אותה התשובה.

ד.א, אני מוכן שסלקום יוציאו את פלט השיחות הנכנסות שלי, אני יכול להבטיח שלא הייתה ולו אחת מבאג, אני יכול להבטיח לכם!
נ.ב
יש לי מיילים, פקסים, בלוגים… אפילו בגוגל אפשר למצוא אותי :-) אבל אף אחד מבאג לא חיפש אותי ולא יצר איתי קשר.

רגע, למה לא חזרת לרמי, הוא נשמע נחמד ומבטיח?

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

טוב, מספרים?

היות ואני לא זוכר את התאריך המדויק (אבל כן זוכר תאריכים בדרך)
את המשקפיים שמתי בשנת 2010 (כלומר לפחות 12 ימים אחורה)
את המשקפיים שמתי בבאג לפני שנסלי (הבת שלי) היתה בת שנה (יום ההולדת שלה הוא ב5 לדצמבר) – כן כן (חודש ושבוע אחורה)

מה זה קשור לYeti לעזאזל?

מילה אישית לבאג, אולי כך הם יבינו את זה בצורה טובה יותר.

אני מצלם סקינקאסטים בבלוג הזה, החודש אני מתחיל סדרה חדשה על Ruby On rails ותכננתי לרכוש מיקרופון (Blue Yeti, גגלו, אל תהיו עצלנים), ביום שישי בעיתון ראיתי שיש אותו בבאג המחיר: 800 שקלים.

תנחשו אצל מי אני לא אוציא את הכסף הזה?

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

אשמח אגב, לתגובות (למטה) ודיון, מה אתם אומרים על העניין?

עדכונים (24 לינואר 2011)

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

Unbelievable, Believe it!

A/B Testing או איך ריילס תעזור לכם להרוויח יותר כסף מהאתר שלכם?

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

  1. יש לכם אתר אינטרנט ואתם רוצים להרוויח ממנו יותר כסף
  2. אתם לא חאפרים ולא בונים אתר אצל חאפרים

טוב, נמשיך?

מהו A/B Testing?

A/B Testing זו בעצם דרך לבדוק את הוריאציות השונות של האפליקציה שלכם ואיך הוריאציות האלה מתפקדות בעיני הגולשים שלכם. מה הייתם אומרים אם הייתי אומר לכם ששינוי כותרת יכול להביא לעלייה של 12% במכירות השבועיות שלכם? מה הייתם אומרים אם הייתי אומר לכם שפונט קטן יותר ושינוי של פסיק בפסקה מסוימת יכול להביא לעליה של 5% נוספים?

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

בעולם התחרותי של היום, עולם שבו יש מוצרים באינטרנט, SAAS) Software As A Service) במחירים שונים ובמקומות שונים יש המון חשיבות למסרים ויזואליים, מיקומם של המסרים האלה ועוד. לפעמים מדובר בדברים בולטים לעין, כאלה שאם תקחו כותב תוכן טוב או מעצב גרפי טוב תצליחו לשפר באחוז ניכר את המכירות שלכם ואת האינטראקציה של גולשים עם האתר. אבל, לא על זה אני מדבר – אני מדבר על השיפורים הקטנים, מיקום של כותרת, מה יהיה כתוב בה וכדומה.

דוגמא ל-A/B Testing במוצר שמכניס מיליונים ויכול להכניס יותר

החבר'ה מ37Signals כתבו פוסט מעלף/מאלף על ניסוי שהם ערכו. הניסוי שהם ערכו דיבר על כותרת ותת כותרת בדף הרשמה לחשבון. זה הכול.
למשל: וריאציה ראשונה
hrhq-signuphead-30day60sec

והוריאציה השנייה
hrhq-signuphead-start30trial

אני יודע, מדגדג לכם על הלשון להגיד שזה לא באמת משנה נכון?

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

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

אבי, אבי, אבי שכנעת אותי, איך אני ממשיך מכאן?

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

אם יש לכם אפליקצית .net או php או אפילו python אפשר כמובן לעשות את זה באמצעות Google Web Optimizer. זה לא סקסי כמו ריילס ולא מובנה בתוך האפליקציה כחלק בלתי נפרד אבל זה כמובן ולידי לגמרי וניתן לביצוע. אפשר גם לבצע את זה באמצעות Google Analytics אבל שוב, זה לא מובנה בתוך האפליקציה ותצטרכו לכתוב הרבה יותר קוד בשביל זה.

אז עם ריילס זה יותר קל?

הכול עם ריילס יותר קל (ונעים ונחמד וכיף :-) )

מה נעשה עכשיו?

עכשיו אנחנו ניקח אפליקציה מאפס ונבנה אותה ל-A/B Testing. אנחנו ניצור טופס הרשמה, בטופס הזה נשים פסקה של טקסט, ונבדוק איך משפיעה הפסקה הזו על כמות האנשים שנכנסים ובאמת נרשמים בסוף.

נתחיל בלייצר אפליקציה שנקרא לה ab_testing.

rails ab_testing

נקבל כמובן אפליקצית ריילס מוכנה.
לא נעבור על כול הקוד המשעמם ונראה איך יוצרים מודל של User וכאלה, אנחנו ניגש לדברים הגדולים יותר באפליקציה, יש לנו מודל של User ויש לנו View שמייצר לנו New User.

הנה הView שלנו:

<% title "Free Sign up" %>

<p>
	Register below to discover the awsomeness of our website
</p>

<p>Already have an account? <%= link_to "Log in", login_path %>.</p>

<% form_for @user do |f| %>
  <%= f.error_messages %>
  <p>
    <%= f.label :username %><br />
    <%= f.text_field :username %>
  </p>
  <p>
    <%= f.label :email, "Email Address" %><br />
    <%= f.text_field :email %>
  </p>
  <p>
    <%= f.label :password %><br />
    <%= f.password_field :password %>
  </p>
  <p>
    <%= f.label :password_confirmation, "Confirm Password" %><br />
    <%= f.password_field :password_confirmation %>
  </p>
  <p><%= f.submit "Sign up" %></p>
<% end %>

וכך זה נראה בדפדפן:
Registration form

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

לבחור את הכלי הנכון

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

הכלי שאנחנו נדבר עליו ונכסה אותו יהיה A/Bingo, זהו בעצם Plugin לרובי און ריילס שמבצע בדיוק את מה שאנחנו צריכים.

התקנה

כול מה שצריך בשביל להתקין את הפלאגין זה כרגיל בריילס, להריץ שורת פקודה:

script/plugin install git://git.bingocardcreator.com/abingo.git

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

script/generate abingo_migration

זה ה-Migration שנוצר לנו כתוצאה מהפקודה:

class AbingoMigration10< ActiveRecord::Migration
  def self.up
    create_table "experiments", :force => true do |t|
      t.string "test_name"
      t.string "status"
      t.timestamps
    end

    add_index "experiments", "test_name"
    #add_index "experiments", "created_on"

    create_table "alternatives", :force => true do |t|
      t.integer :experiment_id
      t.string :content
      t.string :lookup, :limit => 32
      t.integer :weight, :default => 1
      t.integer :participants, :default => 0
      t.integer :conversions, :default => 0
    end

    add_index "alternatives", "experiment_id"
    add_index "alternatives", "lookup"
  end

  def self.down
    drop_table :experiments
    drop_table :alternatives
  end
end

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

rake db:migrate

הגענו לבדיקה הראשונה, יש!

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

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


<% title "Free Sign up" %>

<% if ab_test "signup_paragraph "%>
<p>
 Register below to discover the awsomeness of our website
</p>
<%else%>
<p>
 This is the alternative content
</p>
<%end%>

<p>Already have an account? <%= link_to "Log in", login_path %>.</p>

<% form_for @user do |f| %>
 <%= f.error_messages %>
 <p>
 <%= f.label :username %><br />
 <%= f.text_field :username %>
 </p>
 <p>
 <%= f.label :email, "Email Address" %><br />
 <%= f.text_field :email %>
 </p>
 <p>
 <%= f.label :password %><br />
 <%= f.password_field :password %>
 </p>
 <p>
 <%= f.label :password_confirmation, "Confirm Password" %><br />
 <%= f.password_field :password_confirmation %>
 </p>
 <p><%= f.submit "Sign up" %></p>
<% end %>

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

את השמירה אנחנו נעשה ב-Controller מיד אחרי שמירת המשתמש:

class UsersController < ApplicationController
 def new
 @user = User.new
 end

 def create
 @user = User.new(params[:user])
 if @user.save
 bingo! "signup_paragraph"
 session[:user_id] = @user.id
 flash[:notice] = "You are registered and signed up!"
 redirect_to root_url
 else
 render :action => 'new'
 end
 end
end

אפשר לראות את המתודה שאנחנו משתמשים בה כדי לשמור:

bingo! "signup_paragraph"

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

צפייה בתוצאות המבחן

אנחנו נייצר Controller כדי לצפות בתוצאות:
ֿ

script/generate controller abingo_dashboard

בתוך ה-Controller הזה, אנחנו צריכים לייבא את המודול של Abingo. מומלץ כמובן שה-Controller הזה יהיה נגיש רק לאחר ולידציה של משתמש אבל אנחנו לא ניגע בזה כרגע.

כך נראה ה-Controller שלנו:

class AbingoDashboardController < ApplicationController
  include Abingo::Controller::Dashboard
end

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

  map.abingo_stats "/abingo_stats/:action/:id", :controller=> :abingo_dashboard

עכשיו שיש לנו route מוגדר, בואו ונצפה בתוצאות (אם הserver שלכם פועל, צריך לאתחל אותו):
Abingo Stats

סיכום

נגענו בקצה הקרחון של A/B Testing – גם מבחינת הקונספט וגם מבחינת איך לבצע את זה ב-Ruby on Rails. כמובן שיש עוד הרבה אופציות לבחון, ויש אפשרות לאחד מבחנים תחת כותרת מסוימת וכדומה.
יש דרכים לזהות משתמשים רשומים, לעשות Random של האם יוצג או לא ועוד עשרות שיטות שאפשר לבחון כול מקרה לגופו. האפשרויות (כרגיל) הן בלתי מוגבלות.

ללמוד ריילס כמו זומבי

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

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

נכנסים לעולם הריילס?

משיטוט ברשת מצאתי משהו מדליק שאני חושב ששווה לחלוק אותו ומי שרק נכנס לעולם הריילס ימצא אותו מועיל מאוד.
חברת Envy Labs שמפתחת אפליקציות בריילס וגם אחראית לכול ה Video Tutorials באתר הרשמי של Ruby On Rails הוציאה סדרת Video Tutorials חדשה שנקראת Rails For Zombies מדובר על סדרה של Video Tutorials טובים מאוד ואיכותיים מאוד שעוזרים להכנס לעולם של ריילס יותר בקלות מלעבור על מאמרים באורך 20-30 עמודים.

הנה צילום מסך מתוך האתר, אפשר לראות שלא מדובר בVideo סטנדרטי כמו RailsCasts או כול אחד אחר, הגישה היא קצת אחרת :-)

Screen shot 2010-12-07 at 8.40.00 AM