Các trình quản lý Ruby thông dụng (Ruby Version Managers)

Quản lý phiên bản Ruby là gì?

Trình quản lý phiên bản Ruby là các chương trình cho phép bạn cài đặt, quản lý và sử dụng nhiều phiên bản Ruby. Nếu bạn chỉ mới bắt đầu với Ruby, bạn có thể tự hỏi tại sao bạn có thể cần phải sử dụng nhiều hơn một phiên bản của Ruby. Rất có thể, các chương trình bạn đã viết cho đến nay là "phiên bản bất khả tri"; có nghĩa là, không dựa vào các tính năng của Ruby, không phụ thuộc vào bất kỳ phiên bản Ruby cụ thể nào. Bạn thậm chí không biết rằng bạn đang sử dụng các tính năng dành riêng cho phiên bản đang sử dụng.

Tuy nhiên, điều này không phải luôn luôn xảy ra: Ruby là một ngôn ngữ phát triển với các tính năng được thêm vào, sửa đổi và xóa với mọi phiên bản mới. Cuối cùng, bạn sẽ viết hoặc sử dụng một chương trình Ruby cần một phiên bản Ruby khác, và đó là khi bạn sẽ thấy rằng bạn cần một trình quản lý phiên bản Ruby.


Để cung cấp một ý tưởng về những gì có thể thay đổi, đây là danh sách ngắn về một số thay đổi lớn đối với Ruby trong vài phiên bản chính tại thời điểm viết bài này:

  • Phiên bản 1.9: Thay đổi các biến khối để yêu cầu các biến cục bộ; { a: 5, b: 6 } Cú pháp được giới thiệu cho băm với các symbol; Nhiều thay đổi không tương thích.
  • Phiên bản 2.0: Thêm đối số từ khóa; Đã thêm %i() cú pháp cho symbol.
  • Phiên bản 2.2: Đã xóa một số thư viện lỗi thời.
  • Phiên bản 2.3: Thêm squedgle heredocs ( <<~HERE); Thêm toán tử điều hướng an toàn ( &.); Đã thêm #positive?, #negative?#zero? các phương thức vào lớp Numeric.


Như bạn có thể thấy, mọi phiên bản mới đều có một số thay đổi; đôi khi, các chương trình chạy trên các phiên bản cũ của Ruby không còn hoạt động trong các phiên bản gần đây nữa. Một ngày nào đó, bạn sẽ cần phải cài đặt một phiên bản Ruby khác mà không cần loại bỏ phiên bản Ruby hiện tại của bạn.


Một lý do khác để sử dụng trình quản lý phiên bản Ruby là khi làm việc trên nhiều dự án. Các dự án có xu hướng tiêu chuẩn hóa trên một phiên bản Ruby cụ thể để đảm bảo các nhà phát triển không sử dụng các tính năng ngôn ngữ không được hỗ trợ. Ví dụ, bạn có thể được yêu cầu trợ giúp với một dự án hiện có đã được chuẩn hóa trên phiên bản Ruby 2.1, nhưng phiên bản Ruby cục bộ hiện tại của bạn là 2.3, bạn cần làm việc với các dự án hiện tại của mình. Trong trường hợp đó, bạn sẽ cần sự hỗ trợ của một trình quản lý phiên bản Ruby để giúp bạn quản lý và di chuyển giữa các Ruby khác nhau khi bạn chuyển đổi giữa các dự án khác nhau.

Nên sử dụng trình quản lý phiên bản Ruby nào?

Có hai trình quản lý phiên bản ruby chính sử dụng phổ biến: RVMrbenv. (Ngoài ra còn có các trình quản lý khác như chruby, nhưng chúng được sử dụng ít hơn). Chúng giúp bạn có thể dễ dàng sử dụng nhiều phiên bản của Ruby on cùng hệ thống.


Bạn nên sử dụng trình quản lý phiên bản nào? Điều này một phần phụ thuộc vào sở thích và nhu cầu của riêng bạn, nhưng hầu hết mọi người chỉ chọn một và bắt đầu sử dụng nó. Về mặt chức năng, hai hệ thống thực hiện tất cả các nhiệm vụ mà hầu hết các nhà phát triển cần. Trong hầu hết các trường hợp, có rất ít cách để giới thiệu tính năng này với nhau.


Để biết thông tin về cách cài đặt và sử dụng RVM hoặc rbenv, hãy xem tài liệu tại các trang web tương ứng. Hướng dẫn này, chỉ tập trung chú ý vào cách trình quản lý phiên bản tương tác với hệ thống của bạn.

RVM

Hình dưới cho thấy một cài đặt điển hình của hai phiên bản Ruby khác nhau trong RVM.

$ tree /usr/local/rvm        # the following is partial output
/usr/local/rvm               # RVM path directory
├── gems
│   ├── ruby-2.2.4
│   │   ├── bin
│   │   │   ├── bundle
│   │   │   └── rubocop
│   │   └── gems
│   │       ├── bundler-1.12.5
│   │       ├── freewill-1.0.0
│   │       │   └── lib
│   │       │       └── freewill.rb
│   │       ├── pry-0.10.4
│   │       └── rubocop-0.43.1
│   └── ruby-2.3.1
│       ├── bin
│       │   ├── bundle
│       │   └── rubocop
│       └── gems
│           ├── bundler-1.12.5
│           ├── freewill-1.0.0
│           │   └── lib
│           │       └── freewill.rb
│           ├── pry-0.10.4
│           └── rubocop-0.45.0
└── rubies
    ├── ruby-2.2.4
    │   └── bin
    │       ├── gem
    │       ├── irb
    │       └── ruby
    └── ruby-2.3.1
        └── bin
            ├── gem
            ├── irb
            └── ruby

Quan sát kỹ cấu trúc trên một chút để thấy cách tổ chức các phiên bản Ruby và các Gem trong trình quản lý phiên bản RVM.

Cách RVM hoạt động

Tại lõi của RVM là một tập hợp các thư mục trong đó RVM lưu trữ tất cả các phiên bản Ruby của bạn, các công cụ liên quan của nó (như gemirb), và các Gems của nó. Mỗi thư mục cụ thể cho một phiên bản Ruby. Nếu bạn cần Ruby 2.3.1, RVM sử dụng các tệp trong thư mục ruby-2.3.1; nếu bạn cần Ruby 2.2.4, nó sẽ lấy các tập tin từ thư mục ruby-2.2.4. Lưu ý rằng các tập tin thực thi chuẩn của Ruby được tìm thấy trong thư mục rubies của thư mục chính của RVM, trong khi các gem được tìm thấy trong thư mục gems. Cũng lưu ý rằng số phiên bản Gem có thể khác nhau giữa Ruby: trong trường hợp này, Ruby 2.2.4 sử dụng Rubocop 0.43.1, trong khi Ruby 2.3.1 sử dụng Rubocop 0.45.0.


RVM định nghĩa một hàm shell (xem Bash Reference Manual để biết thông tin về các hàm ) có tên rvm. Shell của bạn sử dụng chức năng này ưu tiên thực hiện rvm lệnh dựa trên đĩa. Có nhiều lý do phức tạp đằng sau việc sử dụng các hàm shell, nhưng lý do chính là một hàm có thể sửa đổi môi trường của bạn, trong khi một lệnh dựa trên đĩa không thể.


Khi bạn chạy rvm use VERSION để thay đổi phiên bản Ruby bạn muốn sử dụng, bạn thực sự gọi hàm rvm. Nó sửa đổi môi trường của bạn để các lệnh ruby khác nhau ứng với từng phiên bản. Ví dụ, rvm use 2.2.4 sửa đổi PATH biến của bạn để lệnh ruby sử dụng Ruby được cài đặt trong thư mục ruby-2.2.4. Nó cũng có những thay đổi khác, nhưng sự thay đổi của PATH là đáng chú ý nhất. Mọi thứ trở nên thú vị hơn khi bạn thiết lập một phiên bản Ruby dành riêng cho dự án của bạn.

Cài đặt các phiên bản Ruby

Một trong những điều đầu tiên bạn nên làm với RVM là cài đặt các phiên bản Ruby bạn cần. Điều này rất dễ thực hiện và chỉ cần thực hiện một lần đối với bất kỳ phiên bản cụ thể nào của Ruby.


Giả sử bạn sắp bắt đầu làm việc trên một dự án yêu cầu Ruby 2.2.4. Điều đầu tiên bạn nên làm là kiểm tra xem bạn đã cài đặt Ruby 2.2.4 chưa. Để thực hiện việc này, hãy chạy:

$ rvm list rubies

rvm rubies

   ruby-2.1.5 [ x86_64 ]
=* ruby-2.3.1 [ x86_64 ]

# => - current
# =* - current && default
#  * - default

Lệnh này cho thấy bạn hiện đang cài đặt phiên bản Ruby 2.1.5 và 2.3.1 và phiên bản 2.3.1 đó là phiên bản hiện tại và phiên bản mặc định. Vì danh sách không hiển thị phiên bản 2.2.4, chúng tôi cần cài đặt nó:

$ rvm install 2.2.4

Thiết lập Ruby local

Bây giờ bạn đã cài đặt Ruby 2.2.4, làm thế nào để bạn nói với RVM để sử dụng nó? Có một số cách, mỗi cách được mô tả trong tài liệu của RVM. Cách dễ nhất là chạy:

$ rvm use 2.2.4

Như chúng ta đã thấy trước đó, lệnh này sửa đổi môi trường của bạn để đảm bảo rằng phiên bản Ruby đầu tiên mà hệ thống của bạn tìm thấy là phiên bản 2.2.4. Sự thay đổi tương tự này cũng hoạt động đối với các lệnh liên quan như gem, irbrubocop.


Thông thường, bạn sẽ không sử dụng lệnh này. Thay vào đó, bạn sẽ xác định một phiên bản mặc định, và sau đó ghi đè lên phiên bản mặc hiện tại. Để xác định phiên bản mặc định - phiên bản Ruby mà RVM sử dụng tự động trong một terminal hoặc shell - chỉ cần chạy:

$ rvm use 2.3.1 --default

Nếu sau này bạn thiết lập một phiên bản khác với Ruby hiện tại, bạn có thể khôi phục mặc định bằng:

$ rvm use default

Bạn muốn sử dụng một phiên bản Ruby khác với một trong các dự án của bạn? Nó không phải là quá khó để chuyển đổi các phiên bản với lệnh rvm use VERSION, nhưng nó dễ bị lỗi: bạn đôi khi sẽ quên thay đổi phiên bản, và cũng có thể quên chuyển về ruby mặc định khi bạn hoàn thành dự án. Thay vào đó, bạn nên tự động thay đổi phiên bản. Đây là nơi mọi thứ trở nên phức tạp một chút.


Có một số cách để làm điều này, cách dễ nhất là tạo một tệp .ruby-version trong thư mục gốc dự án của bạn; nội dung của tệp này chỉ là số phiên bản của ruby mà bạn muốn sử dụng khi sử dụng các chương trình từ thư mục đó. Ví dụ, giả sử chúng ta muốn sử dụng Ruby 2.2.4 cho dự án trong ~/src/magic thư mục của chúng ta. Để thực hiện việc này, hãy chạy:

$ cd ~/src/magic
$ rvm --ruby-version use 2.2.4

Điều này tạo ra một tập tin .ruby-version trong thư mục. Sau khi thiết lập, bạn không cần phải lo lắng về việc thiết lập phiên bản cho dự án này. Để có biện pháp tốt, bạn nên đặt phiên bản mặc định của mình trong thư mục chính:

$ cd ~
$ rvm --ruby-version default

Điều này đảm bảo rằng RVM sử dụng Ruby mặc định khi bạn không ở trong thư mục dự án.


Để sử dụng tệp .ruby-version, RVM sẽ thay thế lệnhcd từ terminal của bạn. Hàm shell gọi lệnh cd, sau đó kiểm tra tệp .ruby-version (nó cũng kiểm tra một số tệp khác mà chúng ta sẽ không thảo luận). Nếu nó tìm thấy một trong các tệp này, nó sẽ truy lục số phiên bản từ tệp, và sau đó sửa đổi môi trường của bạn theo cùng cách mà hàm rvm đó thực hiện. Vì vậy, mỗi khi bạn thay đổi thư mục bằng lệnh cd, RVM sẽ sửa đổi môi trường của bạn để chạy phiên bản Ruby phù hợp.


RVM cũng sử dụng các Gemfile dự án ruby sử dụng Bundler. Nếu Gemfile chứa chỉ thị ruby, RVM sử dụng phiên bản ruby đó để chạy chương trình. Tuy nhiên, lưu ý rằng .ruby-version tệp được ưu tiên.


Xem tài liệu RVM để biết thêm thông tin về quy trình này.


Để xác định vị trí của đường dẫn RVM, hãy chạy:

$ rvm info rvm

ruby-2.2.4:

  rvm:
    version:      "rvm 1.27.0 (latest) by Wayne E. Seguin <[email protected]>, Michal Papis <[email protected]> [https://rvm.io/]"
    updated:      "2 months 6 days 20 hours 34 minutes 44 seconds ago"
    path:         "/usr/local/rvm"

path chính là vị trí đường dẫn của RVM trong hệ thống.


Như chúng ta thấy trong hình đầu, có hai thư mục con quan trọng trong đường dẫn RVM: thư mục rubies và thư mục gems. Thư mục rubies chứa tất cả các Rubies được quản lý bởi RVM, cũng như các tiện ích, thư viện và Gems liên quan của nó. Thư mục gems có cấu trúc tương tự, nhưng mỗi thư mục con chứa một thư mục bin: thư mục này chứa các chương trình thực thi được liên kết với các Gems của bạn, như rubocopbundle.

RVM Gemsets

Tính năng này cung cấp các khả năng tương tự như được cung cấp bởi Bundler: nó cho phép bạn gắn các Gems cụ thể cho từng dự án của bạn. Bundler, cho đến nay, được sử dụng rộng rãi hơn, vì vậy chúng tôi khuyên bạn nên sử dụng nó thay vì gemsets. Tuy nhiên, một ngày nào đó bạn có thể cần phải tìm hiểu về gemsets, vì vậy bạn có thể muốn xem các tài liệu cơ bản của gemsets.

rbenv

Hình dưới cho thấy một cài đặt điển hình của hai phiên bản Ruby khác nhau dưới rbenv.

$ tree /usr/local/rbenv # the following is partial output
/usr/local/rbenv # rbenv root directory
├── shims
│   ├── bundle
│   ├── irb
│   ├── rubocop
│   └── ruby
└── versions
    ├── 2.2.4
    │   ├── bin
    │   │   ├── bundle
    │   │   ├── irb
    │   │   ├── rubocop
    │   │   └── ruby
    │   └── lib
    │       └── ruby
    │           └── gems
    │               └── 2.2.0
    │                   └── gems
    │                       ├── bundler-1.12.5
    │                       ├── freewill-1.0.0
    │                       │   └── lib
    │                       │       └── freewill.rb
    │                       ├── pry-0.10.4
    │                       └── rubocop-0.43.1
    └── 2.3.1
        ├── bin
        │   ├── bundle
        │   ├── irb
        │   ├── rubocop
        │   └── ruby
        └── lib
            └── ruby
                └── gems
                    └── 2.2.0
                        └── gems
                            ├── bundler-1.12.5
                            ├── freewill-1.0.0
                            │   └── lib
                            │       └── freewill.rb
                            ├── pry-0.10.4
                            └── rubocop-0.45.0

Cách thức hoạt động của rbenv

Tại trái tim của rbenv là một tập hợp các thư mục rất giống với các thư mục tại lõi của RVM. Nó lưu trữ và sử dụng các phiên bản ruby, các công cụ liên quan và các Gems từ các thư mục này. Có các thư mục con cho mỗi phiên bản Ruby nằm trong thư mục versions. Nếu bạn cần Ruby 2.3.1, rbenv sử dụng các tập tin trong thư mục 2.3.1; nếu bạn cần Ruby 2.2.4, nó sẽ lấy các tập tin từ thư mục 2.2.4. Lưu ý rằng số phiên bản Gem có thể khác nhau: trong trường hợp này, Ruby 2.2.4 sử dụng Rubocop 0.43.1, trong khi Ruby 2.3.1 sử dụng Rubocop 0.45.0.


Với tư cách là người dùng rbenv hoặc rvm, bạn sẽ cảm thấy rằng cả hai công cụ đều rất giống và chỉ một khác biệt nhỏ về cú pháp. Tuy nhiên, làm thế nào rbenv quản lý Rubies là một sự khởi đầu đáng kể từ cách RVM làm điều đó. rbenv sử dụng một tập hợp các kịch bản nhỏ được gọi là shims. Các kịch bản có cùng tên với các chương trình ruby và Gem khác nhau. Chúng có trong thư mục shims của thư mục cài đặt rbenv chính. Các cài đặt rbenv hợp lệ bao gồm thư mục shims trong PATH; rbenv đặt nó trước bất kỳ thư mục nào khác có chứa ruby hoặc bất kỳ chương trình liên quan nào; điều này đảm bảo rằng hệ thống sẽ tìm kiếm thư mục shims trước. Bằng cách này, khi bạn chạy một trong các lệnh ruby hoặc Gems, hệ thống sẽ thực thi kịch bản lệnh đúng đắn. Các kịch bản shim, lần lượt, thực hiện rbenv exec PROGRAM; Lệnh này xác định phiên bản Ruby nào nên sử dụng và thực hiện chương trình thích hợp từ các thư mục đặc trưng của phiên bản Ruby, ví dụ /usr/local/rbenv/versions/2.3.1/bin.

Cài đặt các phiên bản Ruby

Một trong những điều đầu tiên bạn nên làm với rbenv là cài đặt các phiên bản Ruby bạn cần. Điều này rất dễ thực hiện và chỉ cần thực hiện một lần đối với bất kỳ phiên bản cụ thể nào của Ruby.


Giả sử bạn sắp bắt đầu làm việc trên một dự án yêu cầu Ruby 2.2.4. Trước tiên, bạn cần phải kiểm tra xem bạn đã cài đặt Ruby 2.2.4 chưa. Để thực hiện việc này, hãy chạy:

$ rbenv versions

system
2.1.5
* 2.3.1 (set by /Users/.../project/.ruby-version)

Lệnh này cho thấy bạn hiện đang cài đặt phiên bản Ruby 2.1.5 và 2.3.1, phiên bản 2.3.1 đó là phiên bản Ruby hiện đang được chọn. Vì danh sách không hiển thị phiên bản 2.2.4, chúng tôi cần cài đặt nó. Tuy nhiên, không giống như RVM, rbenv không cung cấp cách cài đặt Ruby mới theo mặc định. May mắn thay, có một sửa chữa dễ dàng: chỉ cần cài đặt ruby-build plugin rbenv. Nếu bạn đang sử dụng Mac với phiên bản Ruby của Homebrew, chỉ cần chạy:

$ brew install ruby-build

Nếu không, hãy làm theo các hướng dẫn cài đặt trên trang Github ruby-build.


Khi bạn đã cài đặt ruby-build plugin, bạn có thể cài đặt Ruby 2.2.4 với:

$ rbenv install 2.2.4

Thiết lập Ruby local

Bây giờ bạn đã cài đặt Ruby 2.2.4, làm thế nào để bạn cho rbenv sử dụng nó? Có một số cách, mỗi cách được mô tả trong tập tin Github README của rbenv. Cách dễ nhất là chạy:

$ rbenv global 2.3.1

Điều này đặt phiên bản mặc định của Ruby để sử dụng là 2.3.1. Từ đó, bạn chỉ cần lo lắng về các chương trình cần một phiên bản khác. Ví dụ, giả sử chương trình trong thư ~/src/magic của bạn cần Ruby 2.0.0. Để làm điều đó, hãy chạy:

$ cd ~/src/magic
$ rbenv local 2.0.0


Điều này tạo ra một tập tin .ruby-version trong thư mục ~/src/magic; khi bạn chạy bất kỳ chương trình dựa trên Ruby nào được lưu trữ trong thư mục này, hãy rbenv kiểm tra tệp .ruby-version và sử dụng phiên bản Ruby đó cho chương trình. Nếu không có tệp .ruby-version nào , hãy khởi chạy rbenv tìm kiếm một tệp .ruby-version thay thế và nếu nó vẫn không thể tìm thấy tệp, nó sẽ sử dụng phiên bản toàn cầu của Ruby.

Lưu ý rằng tệp .ruby-version này giống với tệp .ruby-version được RVM sử dụng: cùng tên, cùng nội dung, cùng chức năng và cùng một chuỗi tìm kiếm.

Xem tài liệu về rbenv để biết thêm thông tin về quy trình này.


Rbenv tạo thư mục lúc cài đặt được gọi là thư mục gốc rbenv; nó cũng cài đặt tất cả các tệp liên quan đến rbenv, bao gồm tất cả các phiên bản Ruby và Gems mà nó quản lý, trong thư mục này. Để xác định vị trí của thư mục gốc rbenv, hãy chạy:

$ rbenv root

/usr/local/rbenv

Tóm lược

Trình quản lý phiên bản Ruby cho phép bạn quản lý nhiều phiên bản Ruby, các tiện ích (chẳng hạn như irb) được liên kết với mỗi phiên bản và RubyGems được cài đặt cho từng phiên bản Ruby. Với trình quản lý phiên bản, bạn có thể cài đặt và gỡ cài đặt phiên bản ruby và đá quý; chạy phiên bản ruby cụ thể với các chương trình và môi trường cụ thể.

Hai trình quản lý phiên bản chính, RVMrbenv, có chức năng tương tự, ít có sự khác biệt giữa chúng. Theo mặc định, RVM có nhiều tính năng hơn, nhưng plugin rbenv cung cấp nhiều chức năng không được cung cấp bởi cài đặt cơ bản của rbenv. RVM hoạt động bằng cách tự động quản lý môi trường của bạn, chủ yếu bằng cách sửa đổi biến PATH của bạn và thay thế lệnh dựng sẵn cd bằng shell function nhận biết RVM; rbenv hoạt động bằng cách thay đổi PATH và một số biến môi trường khác của bạn .

Như chúng ta đã thấy, các chương trình Ruby thường cần một phiên bản cụ thể của Ruby và các phiên bản cụ thể của các Gems mà nó sử dụng. Trình quản lý phiên bản Ruby bao phủ hầu hết các vấn đề phát sinh từ các yêu cầu khác nhau, nhưng đôi khi bạn sẽ thấy rằng chúng là không đủ. Ví dụ, bạn có thể cần phải sử dụng Ruby 2.2.4 cho hai dự án khác nhau thay vì 2.3.1 mặc định của bạn, nhưng bạn cũng có thể cần các phiên bản riêng biệt của Rails Gem, 4.2.7 cho một dự án và phiên bản 5.0.0 cho một dự án khac. Trong khi cả hai RVM và rbenv (với sự trợ giúp của một plugin) có thể xử lý các yêu cầu này, thì đường dẫn dễ dàng hơn và phổ biến hơn là sử dụng một RubyGems được gọi là Bundler. Chúng ta thảo luận về Bundler trong phần tiếp theo.


Reference: Core Ruby Tools


~HAPPY CODING!