Managing Multiple Rubies on Windows

One thing that I have missed about my move from an Apple MacBook Pro to a Windows Surface Book was the ability to easily configure multiple Ruby versions on the machine. In the past I have done this with chruby and direnv and whilst the latter is written in Go the way in which Windows executes scripts means this setup does not work.

So I set about finding an alternative. After much research I found one that works almost as well and it is called URU. It is Go application that manages multiple Ruby versions for any platform.

This post details how to install URU and then unpack and configure different Ruby versions for it to manage. I will be honest and say that it is not as simple as double clicking a file, but most of this only needs to be done once. The benefits far outweigh the mild irritation of the setup.

Conventions

PowerShell understands ~ as the home directory, like shells on *NIX environments do. It also recognises the / character as a directory separator.

This notation is used extensively throughout this post. For example, my Windows username is russells so the path ~\Downloads refers to C:\Users\russells\Downloads.

Command prompt does not understand these conventions.

Requirements

  • Chocolatey - Package manager for Windows
  • 7Zip - The Ruby downloaded in this post is packed using 7z

Installing URU

I am using Chocolatey to manage packages on my Windows machines, so this is how I will install the package in this post. There are other methods for installation that can be found here.

Whilst the software can be installed using Chocolatey it is not in any of the repositories at the moment, so the NuGet package must be downloaded manually and then installed using choco.

The version as of writing is 0.8.3 and it is assumed that the package has been downloaded to ~/Downloads.

  • Download the NuGet package from here
  • Open a PowerShell prompt with elevated privileges
  • Use the following to install using the following:
$> cd ~\Downloads
$> choco install uru.0.8.3.pkg
  • Close the current PowerShell prompt and open a new non-admin one.

Installing Rubies

Now that URU is installed it needs to be told about the Rubies that are available. When Ruby is installed on Windows it is usually using an installer which means it is globally installed and there is only one version in the path. Using URU changes this.

Like on a *NIX based systems several Rubies are unpacked into a central location and then referenced. The first part of unpacking the ruby has to be done manually and then URU informed about the unpacked ruby.

In this post Ruby 2.3.3 will be made available, but any Ruby compiled for Windows should work in the same way.

  • Make a directory for the unpacked Rubies, e.g. ~/tools/rubies
  • Download the Ruby 2.3.3 Zip file from RubyIntaller for Windows. (This is the 64bit version)
  • Using 7zip unpack to ~/tools/rubies
  • [Optional] Rename the ruby-2.3.3-x64-mingw32 subdirectory to ruby-2.3.3; whilst not necessary it does make configuring URU easier.

Registering with URU

Now that a Ruby version has been unpacked it needs to be registered with URU. In a PowerShell (or Command Prompt) type the following:

PS> uru admin add C:\Users\russells\tools\rubies\ruby-2.3.3\bin --tag ruby-2.3.3

Listing registered Rubies

URU has the ability to show the registered rubies using uru ls.

Configuring the Ruby Development Kit

There are now different methods for installing the development kit based on the version of Ruby that is being unpacked. Please use the appropriate method below for your version of Ruby.

These instructions are for the RubyIntaller for Windows Ruby Zip files. If you have downloaded a different type of Ruby please use instructions for it on how to configure the development kit.

Ruby 2.0 to Ruby 2.3

Often, when installing Gems, it is necessary to have the development kit installed so that the gems can be natively compiled. This will need to be done for every ruby that is unpacked.

The development kit is a MSYS/MinGW based toolkit than enables you to build many of the native C/C++ extensions available for Ruby.

  • Download the Ruby Development kit
  • Run the downloaded file, which will ask for the location of the unpack directory. I suggest using something like ~/tools/devkit.
  • Open a PowerShell command prompt and run the following commands. This will create an empty config.yml file.
PS> cd ~\tools\devkit
PS> ..\rubies\ruby-2.3.3\bin\ruby.exe dk.rb init
  • Modify the config.yml file so that it includes the path to the Ruby (or rubies) that you need to be enhanced with the Development Kit. For example:
- C:/Users/russels/tools/rubies/ruby-2.3.3

Notice the forward slash for the directory separator. If you prefer to use the \ character it must be escaped by the \ character so it would become C:\Users\russells\tools\rubies\ruby-2.3.3

  • [Optional] To check that the file is valid and that it has picked up the filepath correctly run the following command:
PS> ..\rubies\ruby-2.3.3\bin\ruby.exe dk.rb review
  • Run the installation which will iterate around all the specified rubies and enhance them.
PS> ..\rubies\ruby-2.3.3\bin\ruby.exe dk.rb install

Ruby 2.4 onwards

With this version of ruby the development kit has been replaced with the MSYS2 toolkit. Please refer to this page for instructions on how to install and configure the toolkit.

Using a Ruby

So now a Ruby has been unpacked and registered with URU, but how is it used as it is not installed to any path?

This is as simple as running the URU command with the name of the registered Ruby that you wish to run, e.g.

PS> uru ruby-2.3.3

Automatically selecting Ruby Version

If you are a Ruby developer you will be familiar with the .ruby-version file that can be added to a project. This file is used in conjunction with things like RVM and Chruby on *NIX environments to automatically select the version of ruby to use. Well good news as URU can use this file as well.

By using uru ls it is possible to see which ruby is being used. If none of the listed rubies have the => at the beginning of the line then no Ruby is currently active.

  • Create a file called .ruby-version in the project directory with the name of one of the rubies, e.g.
PS> echo "ruby-2.3.3" > .ruby-version

Unfortunatley when using echo on Windows to create a new file, it creates the file with the UTF16-LE encoding which is not readable by URU.

To make matters even more infuriating you can set the encoding to UTF8 when using the PowerShell cmdlet Set-Content but this created a UTF8-BOM file which URU cannot read either.

The only way to guarantee the encoding is to open up the file in an editor such as VSCode, Sublime or Notepad++ and explicitly set the encoding.

  • Run the uru auto to select the ruby to run from the file

Bonus - Register ChefDK Ruby

If you are a Chef user then you will be familiar with the chef exec construct for running Ruby commands. However this can made easier by registering the ChefDK ruby with URU so that it can be selected as necessary.

Assuming ChefDK has been installed in the default directory run the following command:

PS> uru admin add c:\opscode\chefdk\embedded\bin --tag chefdk

Now using the ChefDK ruby version is as simple as running uru chefdk.

Summary

I am pleased with this setup, so much so that I have replicated it across all my Windows machines. It is not as convenient as using direnv which will read a file as I enter the directory and set up the environment, but it is not far off .

To Do

  • Create a Chef Cookbook for URU so that it can be installed and managed using Chef
  • See if it is possible to use direnv on Windows with URU to automatically run the uru auto command.
Share Comments