แยก Ruby version/gemset ของแต่ละแอพออกจากกันด้วย RVM

Posted on July 16, 2015
By Karun Siritheerathamrong

ต่อเนื่องจากโพสต์ก่อนหน้านี้เรื่อง วิธีติดตั้ง Ruby และ Rails อย่างง่ายด้วย RVM และ Bundler & Gem คู่พิฆาต Dependencies

เมื่อเราพัฒนาหลายๆ แอพพลิเคชั่นพร้อมๆ กัน ก็มีโอกาสที่บางแอพฯ จะเรียกใช้ gem เดียวกันกับแอพฯ อื่นๆ แล้วจะทำให้เกิด “ปัญหา” ที่หลายๆ คน มองข้ามไป นั่นคือ….. การตีกันของ gem ต่างๆ ในระบบ

ตัวอย่าง…

โปรเจ็ก A

  • ใช้ gem mongoid (สมมติให้ตอนติดตั้งเป็นเวอร์ชั่น 3.1.2)
  • โค้ด / วิธีการ query ข้อมูล และ API เป็นไปตาม mongoid 3.1.2

โปรเจ็ก B

  • ใช้ gem mongoid (สมมติตอนเริ่มทำโปรเจ็ก mongoid เป็นเวอร์ชั่น 4.0.1 แล้ว)
  • โค้ด / วิธีการ query ข้อมูล และ API เป็นไปตาม mongoid 4.0.1

ดูเผินๆ เหมือนไม่มีปัญหาอะไรใช่ไหม? มันคงจะไม่เกิดปัญหาอะไรใช่ไหม?……

ไม่ใช่ครับ

เมื่อเวลาใช้งานจริง อาจจะเกิดปัญหาขึ้นได้ เนื่องจาก เมื่อเราสั่ง gem install ตามลำดับนี้

gem install mongoid กับโปรเจ็ก A

จากนั้น

gem install mongoid กับโปรเจ็ก B

เครื่องจะทำการติดตั้ง mongoid เวอร์ชั่น 3.1.2 จากนั้นก็จะติดตั้งเวอร์ชั่น 4.0.1 ลงไปตามลำดับ

เมื่อเราสั่งโหลด Ruby console ขึ้นมาด้วยคำสั่ง `irb’ หรือ สร้างไฟล์ ruby script ขึ้นมา เอาไว้ที่ทั้งสองโปรเจ็ก

แล้วให้รัน / มีคำสั่งดังนี้

[code language="ruby"]
require 'mongoid'
puts Gem.loaded_specs['mongoid'].version
[/code]

สิ่งที่จะแสดงออกมาหลังจากรันคำสั่ง / script จากทั้งสองโปรเจ็กคือ

[code]
#<Gem::Version "4.0.2">
[/code]

วิธีแก้ปัญหา

  1. สร้างไฟล์ชื่อ .ruby-version ซึ่งเนื้อหาข้างในจะเป็นเวอร์ชั่นของ Ruby นำไปไว้ที่โฟลเดอร์ของโปรเจ็ก
  2. สร้างไฟล์ชื่อ .ruby-gemset ซึ่งเนื้อหาข้างในจะเป็นชื่อชอง gemset นำไปไว้ที่โฟลเดอร์ของโปรเจ็ก
  3. รันคำสั่ง
    cd . 
  4. ตรวจสอบว่าจะต้องขึ้นผลลัพธ์ประมาณนี้ โดยการรันคำสั่ง
    rvm current
    [code]
    /home/karun/projects/test_na
    ruby-2.2.1 - #gemset created /home/karun/.rvm/gems/ruby-2.2.1@test-na
    ruby-2.2.1 - #generating test-na wrappers..........
    [/code]

จากนั้นเราสามารถสั่ง gem install ได้โดยไม่ต้องกลัวว่า gem ต่างๆ ในโปรเจ็กจะตีกันอีกแล้ว

ตัวอย่างข้อมูลของไฟล์ .ruby-version ที่ระบุว่าจะใช้ Ruby เวอร์ชั่น 2.2.1

[code]

ruby-2.2.1

[/code]

ตัวอย่างข้อมูลของไฟล์ .ruby-gemset ที่ระบุจะใช้ gemset ชื่อ test-na

[code]

test-na

[/code]

*** เราสามารถใช้การแยก gemset กับโปรเจ็กที่เป็น Rails ได้อีกด้วย เมื่อสั่ง bundle install แล้ว gem ต่างๆ จะไม่ชนกัน ***