אם תנסו לפתח רובי על מערכת ההפעלה \”חלונות\” – RVM עשוי להיות האכזבה הראשונה שלכם. כ\”כ הרבה מדריכים מניחים שאתם משתמשים ב RVM – אבל RVM לא רץ על חלונות (רק יוניקס / לינוקס / מק). החלופות הקיימות לחלונות (למשל pik) – הן לא ממש טובות.
RVM הוא קיצור של \”Ruby enVironment Manager\” (כפי שמוסבר באתר), אם כי באותו האתר, בכותרת בגדול, מצוין דווקא הקיצור הישן (\”Ruby Version Manager\”). צחוקים.
RVM מאפשר:
- להתקין גרסאות רובי שונות (נקראות Rubies) על אותה מערכת ההפעלה, ללא התנגשות (למשל 1.9.3, 2.1.0, ו 2.1.5).
- להחליף בכל רגע את גרסת הרובי \”הנוכחית\” בפקודת shell פשוטה.
- להצמיד גרסת רובי מסוימת לתיקיה מסוימת במערכת הקבצים (כלומר: לפרויקט רובי שנמצא בתיקיה הזו).
- לנהל רשימה נפרדת של Gems (נקרא gemset) לכל גרסת רובי או לכל פרויקט.
- RVM מפשט את ההתקנה של רובי. בג\’אווה זה היה פשוט, ואין קושי להתקין כמה גרסאות זו לצד זו.
- אי-היכולת לנהל רשימה נפרדת של Gems לכל פרויקט היא סוג של \”חור\” במנגנון ה Gem המקורי. RVM מציג פתרון לבעיה זו אם כי גם Bundler, כלי נפוץ מאוד אחר – גם הוא מציע פתרון לאותה הבעיה.
- התאימות לאחור של המפרשנים של רובי (יהיו אלו Rubinius, YARV, או JRuby) היא פחות טובה מהמקובל בג\’אווה. אם פיתחתם אפליקציה על רובי 2.0.3, כנראה שלא תרצו להריץ אותה על מפרשן של גרסה 2.0.5, ובטח לא על מפרשן של 2.2.0.
יש פה גם עניין תרבותי, אני חושב: הסבירות שמפתחי ג\’אווה יבחרו לעבוד על JDK 1.7 עם patch level מסוים – כי פרויקט אחר שלהם על אותה הגרסה (למרות שיש כבר ג\’אווה 8), היא גבוהה יותר מהסיכוי שמפתחי רובי יעשו כן. אנשי רובי נמשכים חזק יותר ל\”חדש\”. לעבוד עם רובי 2.1.3, כשיש רובי 2.2.0 (בטא) כבר בחוץ? חחחחחחח!
פוסט זה שייך לסדרה: רובי (Ruby) למפתחי ג\’אווה ותיקים
![]() |
הדוד בוב (Robert C. Martin), בתחפושת \”נער הרובי\” שלו… |
אמונות מקובלות לגבי RVM – נכון, או לא נכון?
\”RVM מתאים בעיקר לפיתוח, ב Production הוא עושה בעיות וכדאי להימנע ממנו\”.
ובכן, RVM מבצע שינויים בקובץ ה bashrc. בזמן ההתקנה.
הוא עצמו כתוב ב shell script, והוא מניח שמספר כלי shell זמינים לו ב path (למשל awk, sed, tar, git וכו\’), וכמו כן הוא מניח על זמינות של כמה פקודות shell (מערכים וכו\’).
אני עובד עם zsh – והוא עובד לי מצוין. אם אתם עובדים עם shell אחר, כנראה שיהיה עליכם לעשות כמה צעדים ידניים (קונפיגורציות + וידוא זמינות הכלים הנחוצים ל RVM). חפשו בגוגל.
זו הזדמנות טובה לספר שיוצר RVM הצליח לגייס לפני כשנה תקציב שיעזור לו לשכתב את RVM מחדש לשפת רובי. באופן זה הוא אמור להיות יציב יותר, להתפתח מהר יותר, ולהיות זמין בקלות על כל ה Shells ואפילו על חלונות (!).
אסור להפעיל RVM עם Sudo (וללא רשות מרגע ודודלי!)
האיסור רלוונטי להתקנה של RVM עצמו ופעולות gem install – שכאשר משתמשים ב RVM אין לבצע מתוך חשבון עם הרשאות root. לא רק שהפקודה עלולה להיכשל, היא יכול לגרום לנזק להתקנה של ה Gem או של RVM – שיהיה לא-קל להתאושש ממנה.
מקור המגבלה הוא השפה בה RVM כתוב, שהיא shell script. כשעובדים ב shell scripts, כמה משתני סביבה ו paths הם שונים בתור משתמש root – מה שמשבש את ההנהגות של RVM, וכנראה ללא דרך מוצא פשוטה.
\”את RVM לא ניתן להסיר! פרמטו את המחשב – בכדי להסיר אותו!!\”
יש בזה משהו נכון: ההסרה של RVM היא לא כ\”כ פשוטה. גם ההתקנה עלולה להסתבך, לפעמים.
מצד שני, אם תחפשו מעט בגוגל – תוכלו למצוא סדרה של כמה צעדים פשוטים שיסירו את RVM בקלות.
האמונה הזו כנראה נובעת מאנשים שמצאו תשובות שגויות / חלקיות בגוגל, מה שסיבך להם אח\”כ את תהליך ההסרה. או אולי, חס וחלילה, מישהו שהתקין את RVM עם sudo, ואז בלי sudo – ואז ניסה להסיר….
RVM הוא העבר, יחי rbenv! … או chruby! … ?!
RVM הוא כנראה הכלי הנפוץ בתחומו, מה שעשוי אוטומטית (במיוחד בקהילה כמו זו של רובי) לגרום לכלים האחרים להראות אטרקטיביים מעט יותר. שתי האלטרנטיבות הנפוצות הן rbenv ו chruby.
אם תבחנו את ההבדלים בין RVM ל rbenv, למשל – תראו שהכלים דיי דומים. RVM מכסה קצת יותר קרקע, והיא ממומשת בצורה אחרת: עטיפה פקודת ה cd של ה shell (פקודה מאוד נפוצה) ובמחיר של כמה עשרות ms נוספים לכל הפעלה של הפקודה, בעוד rbenv עוטפת בעזרת \”shims\” את gem את רובי ועוד כמה קבצים אחרים – מה שמסוכן לא פחות.
לא יודע… עבורי הרעיון של ללכת עם האופציה הבסיסית והפשוטה (יהיה זה Sinatra או Lotus) – דווקא קוסם.
אז איך נראית העבודה ב RVM (בקצרה)?
יתקין את רובי גרסה 2.0.1, וייצור לה gemset בשם default. ניתן לציין גם patch level מדויק.
כדי להתחיל להשתמש בגרסה הזו, פשוט מפעילים את הפקודה:
האם אנו רוצים לשנות ידנית את גרסת הרובי בכל מעבר בין פרויקטים? ברור שלא!
ניתן ליצור קובץ rvmrc. שיעשה זאת עבורנו. נכנס לתיקיית הפרויקט ונקליד:
כשנצא מהתיקייה ונחזור אליה – RVM ישאל אותנו אם אנו יצרנו את הקובץ, ואם כן, הוא \”יאשר\” אותו ויחליף את גרסת הרובי הנוכחית אוטומטית בכל כניסה לתיקיה. את קובץ ה rvmrc. כדאי להפקיד ב git repository שלנו.
האמת, שיש תקן, עליו הסכימו מנהלי הגרסאות השונים של רובי לקבצי קונפיגורציה. בואו נשתמש בו:
$ echo \’2.0.0\’ > .ruby-version
יש יתרון בסטנדרטיות לא רק במחשבה על מעבר מהיר (הפעלת שורה אחת פחות?!) לכלי ניהול גרסאות אחר – אלא בעיקר כי מספר כלי צד-שלישי מכבדים את הפורמט המשותף, אך לא מכבדים את קובץ ה rvmrc.
היתרון של קובץ rvmrc. הוא שמדובר בקובץ סקריפט לכל דבר שמופעל בעת כניסה לתיקיה. השורה שהכנסנו למעלה rvm use היא פקודת shell לכל דבר, וניתן להוסיף פקודות נוספות.
אם כבר ציינו כלים, אני עובד עם RubyMine שמכבד דווקא רק את הצורה הארוכה (והתקנית) לתיאור גרסת רובי. נעדכן את הקובץ, כך שרובי-מיין יקשר אוטומטית את הפרויקט לגרסת הרובי הנכונה:
יופי!
עכשיו בואו נרחיב את השימוש ל gemsets. ניצור gemset חדש (בשם \”project_name\”) תחת גרסת הרובי הנוכחית (2.0.1), ונהפוך גם את ה gemset שיצרנו להיות הנוכחי הנוכחי:
הקונבנציה המקובלת היא לקרוא ל gemset כשם ה root folder של הפרויקט. RVM משתמש בפורמט של ruby_version@gemset_name בכדי לתאר צמד. נזכיר ש gemset משוייך לגרסת רובי מסוימת.
מכיוון שאנו רוצים שגם המעבר ל gemset יהיה אוטומטי בכניסה לתיקיה, נגדיר קובץ קונפיגורציה:
ייתכן ותתקלו בהמלצה לוותר על קובץ ה ruby-gemset. ולכתוב בקובץ ה ruby-version. את הפורמט של RVM, קרי \”ruby-2.0.0@project_name\”. זה יעבוד לכם עם RVM, אך עלול לא לעבוד עם כלים אחרים (זה לא חלק מהסטנדרט).
אם נקרא ל gem list – נראה רק את ה default gems שמגיעים עם רובי גרסה 2.0.0 (יש כ 14 כאלה).
נוודא, ליתר בטחון, שאנו משתמשים בגרסת הרובי וה gemset שאליו התכוונו, ע״י פקודת
(הדרך הכי קצרה שאני מכיר)
נתקין gem לדוגמה, ונראה שהוא נוסף ל gemset:
אתם יכולים לקרוא ל rvm use 2.0.0 ואז ל gem list בכדי לראות שה gem שהתקנו לא נמצא ב default gemset.
את ה gem עצמו תוכלו למצוא בתיקיית ה gemset המנוהלת תחת התיקייה rvm/gems./~.
זה, פחות או יותר, הבסיס.
RVM מספק עוד כל מיני יכולות. הנה פקודה נחמדה:
אלטרנטיבה לשימוש ב gemsets
למה? אולי זה עושה יותר סדר בראש, אולי בגלל יכולות של bundler כמו פקודת bundle update שתעדכן את כל ה gems לגרסאות עדכניות – כולל התלויות שלהן. לכו תעשו את זה ידנית בעזרת gem update…[א]
- קובץ ה Gemfile מנהל עבורכם את הגרסאות השונות של ה gems.
- את התקנת ה gems אתם עושים, כנראה, ע\”י עדכון של ה Gemfile והרצת הפקודה bundle install.
RVM נוצר בכדי לפתור \”חורים\” ב RubyGems, אבל הנה bundler עושה את אותו הדבר בעצמו.
מצוין לכם ב Gemfile את rake גרסה 10.0 בעוד פרויקט אחר דרש את גרסה 10.1? – שתי הגרסאות מותקנות ובהפעלת הפקודה rake תרוץ הגרסה המאוחרת (10.1) על אף שהגרסה המצוינת ב Gemfile היא 10.0. יותר גרוע: התלויות של rake גם הן תבחרנה בגרסה המאוחרת ביותר שצוינה כתואמת. \”סמוך על סחבק\” – מה שנקרא.
סיכום
האם ייתכן שכלי כ\”כ נפוץ כתוב בעצם ב shell script (כלומר: 20 אלף שורות של shell script), עם כל המגרעות והבעיות שבדבר? שכל כלי בתחום מציב כמה ״חוסרי נוחות״ שיש להתמודד איתם?
ברוכים הבאים לעולם הרובי! אני בעצמי עוד מתרגל 🙂
בסופו של דבר, כמה חוסרי נוחות קטנים, לא עצרו את קהילת רובי לייצר פרויקטים גדולים ומרשימים. כשאני אומר זאת, אני מרגיש כמו אמריקאי שמתפלא כיצד חיים בישראל, כשאין .
בסופו של דבר, בעת כתיבת הקוד, שזה (בשאיפה) היכן שרוב זמן המתכנת הולך – רובי מציעה הרבה נוחיות שמתכנתי ג׳אווה יכולים רק לחלום עליהן. אז נכון… ה tooling הם פחות מלוטשים.
שיהיה בהצלחה!
—
[א] נראה ש RVM מקנאה ביכולת הזו, והיום היא מציעה יכולת דומה בעזרת הפקודה do:
—
מקורות / לינקים רלוונטיים:
Deep Dive: RVM (this post goes deeper, imho)
מאמר מעולה!!!השכלנו 🙂