Skip to content

Instantly share code, notes, and snippets.

@fnichol
Created February 26, 2012 01:23
Show Gist options
  • Save fnichol/1912050 to your computer and use it in GitHub Desktop.
Save fnichol/1912050 to your computer and use it in GitHub Desktop.
A Common .ruby-version File For Ruby Projects

A Common .ruby-version File For Ruby Projects

Background

I've been using this technique in most of my Ruby projects lately where Ruby versions are required:

  • Create .rbenv-version containing the target Ruby using a definition name defined in ruby-build (example below). These strings are a proper subset of RVM Ruby string names so far...
  • Create .rvmrc (with rvm --create --rvmrc "1.9.3@myapp") and edit the environment_id= line to fetch the Ruby version from .rbenv-version (example below).

Today I learned about another Ruby manager, rbfu, where the author is using a similar technique with .rbfu-version.

So...

What if we had an ecosystem of fabulous Ruby managers that all understood the semantics of a generic dotfile such as .ruby-version? The file's contents would be nothing more than a string representing a version of Ruby.

Perhaps We Can

Without a more thorough investigation (here be dragons?), the project-level updates might be:

  • rvm: A modification to scripts/functions/rvmrc to check for .rvmrc and then .ruby-version (invoking something like rvm use $(cat $working_dir/.ruby-version)). If the user requires a customized .rvmrc they can wire in .ruby-version themselves (i.e. environment_id="$(cat .ruby-version)@gemset").
  • rbenv: A modification to libexec/rbenv-version-file to check for .rbenv-version and then .ruby-version.
  • rbfu: A modifcation to bin/rbfu to first check for .rbfu-version and then .ruby-version.

In all 3 cases, it seems reasonable to prefer an implementation-specific file over the generic version--no loss of default behavior.

So?

Feedback? Ideas? Questions?

#!/usr/bin/env bash
# This is an RVM Project .rvmrc file, used to automatically load the ruby
# development environment upon cd'ing into the directory
# First we specify our desired <ruby>[@<gemset>], the @gemset name is optional,
# Only full ruby name is supported here, for short names use:
# echo "rvm use 1.9.3" > .rvmrc
environment_id="$(cat .rbenv-version)@myapp"
# Uncomment the following lines if you want to verify rvm version per project
# rvmrc_rvm_version="1.10.3" # 1.10.1 seams as a safe start
# eval "$(echo ${rvm_version}.${rvmrc_rvm_version} | awk -F. '{print "[[ "$1*65536+$2*256+$3" -ge "$4*65536+$5*256+$6" ]]"}' )" || {
# echo "This .rvmrc file requires at least RVM ${rvmrc_rvm_version}, aborting loading."
# return 1
# }
# First we attempt to load the desired environment directly from the environment
# file. This is very fast and efficient compared to running through the entire
# CLI and selector. If you want feedback on which environment was used then
# insert the word 'use' after --create as this triggers verbose mode.
if [[ -d "${rvm_path:-$HOME/.rvm}/environments"
&& -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
then
\. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
[[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]] &&
\. "${rvm_path:-$HOME/.rvm}/hooks/after_use" || true
else
# If the environment file has not yet been created, use the RVM CLI to select.
rvm --create "$environment_id" || {
echo "Failed to create RVM environment '${environment_id}'."
return 1
}
fi
@ktaragorn
Copy link

This is needed because with Gemfile, Bundler checks against RUBY_VERSION if it matches

    Your Ruby version is 2.3.0, but your Gemfile specified 2.3.0-preview2

Right now I have 2.3.0-preview2 to make rvm happy in.ruby-version and 2.3.0 in Gemfile to make bundler happy

@FranklinYu
Copy link

@ktaragorn I guess you should specify the patch level with :patchlevel => 'preview2'.

It’s also possible to restrict the patchlevel of the Ruby used by doing the following:

ruby '1.9.3', :patchlevel => '448'

so you can have the exact version in both .ruby-version and Gemfile.

@g13013
Copy link

g13013 commented Oct 10, 2016

@mislav your explanation about fuzzy matching upsets me a little bit, developers are adults and they know how to deal with version problems, supporting fuzzy versions will allow teams to chose whatever fits theres needs, if "paranoid" people like you still want to be very careful about the version they use, they still have the possibility to force the exact version.

@MartinNowak
Copy link

Regarding https://gist.github.com/fnichol/1912050#gistcomment-682506

If you want cute shortcuts & aliases, you can always make symlinks.

ln -s 2.3.5 ~/.rbenv/versions/2.3

Is a clean and simple solution to alias an installed ruby version.

rbenv versions

* 2.3 (set by .ruby-version)
  2.3.5

@megatux
Copy link

megatux commented May 26, 2022

What about asdf VM and its .tool-versions? e.g.

cat .tool-versions

postgres system
ruby 2.7.5
redis 6.0.8
yarn 1.22.5
nodejs 16.9.1

@andyw8
Copy link

andyw8 commented Jan 2, 2024

Specification for .ruby-version (rubygems discussion).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment