My latest Rails project is more or less and experiment for me to break lots of things and learn in the process. I have the latest version of Ruby specified in my gemfile:
ruby '2.2.3'
And I also have a .ruby-version
dotfile in the project, with the following contents:
2.2.3
Other than the obvious duplication, what is wrong with this? What is the purpose of both conventions? If I should only have one convention for listing my Ruby version, why should I have one (Gemfile) over the other (dotfile)?
Is it perfectly fine to have both conventions in a project?
I am going to be the only maintainer of this experimental project, and dont feel it will be an issue having to maintain this one subtle duplication. I dont intend to upgrade Ruby for this project, and if I do, I wont have an issue remembering to do it in both places. Other than this detail, I certainly avoid any such duplication in my applications' codebases.
They were each developed by different teams at different times, and are used by different software.
Listing a ruby version in the Gemfile is a feature in bundler.
As the Gemfile is mostly only used by bundler, it will mainly only effect things when you run the with bundler -- using bundle exec
, or software (like Rails) that automatically triggers bundler for you. It's effect is simply to error out and refuse to run if you aren't using the version of ruby specified. It's a requirement -- run under this ruby, or I'll throw an error warning you you're running under the wrong ruby.
However, heroku also pays attention to the version specified in the Gemfile, and will run under that version. Heroku decided to use the feature in bundler too. But most other software, on your workstation, or even travis, does not use that convention. (Travis makes you edit your .travis.yml ENV to specify ruby version to use).
The feature in bundler was introduced in Bundler 1.2 in August 2012.
The .ruby-version file was first introduced by rvm, the first ruby version manager. If you are using rvm, and you switch into a project direcotry with a .ruby-version
file, rvm will automatically switch your shell to using the ruby version specified.
I'm not sure when rvm introduced this feature, but I think before the Gemfile "ruby" feature.
Since rvm introduced it, other ruby version switching software like rbenv and chruby have adopted it too to do the same thing -- automatically switch to the ruby version specified when you cd
into the directory. Although I think with rbenv and chruby both it may be an optional feature.
So they were different features introduced into and supported by different software packages at different times, doing somewhat different things.
I agree it would be annoying to maintain both, and keep them in sync.
They are both actually optional, you don't need to use either one. Except that you might need to use the Gemfile ruby spec for heroku, to tell it which ruby you want it to run.
I don't personally use either. But if you need to work in different ruby versions in different projects, and find it convenient to have your ruby version manager (rvm, rbenv, or chruby) automatically switch to the right project-specific ruby version, .ruby-version
might be useful.
Except for heroku purposes, listing ruby in the Gemfile is mostly just to keep yourself from making a mistake, for instance on deployment. Or perhaps an in-house automated deployment or CI environment could use them somewhat like heroku does, or perhaps other cloud deployment stacks will or have adopted it. I think many have found it not too useful though -- this one too, I wouldn't use until you run into or see a problem that it's solving. One inconvenience some people have with listing ruby versions in Gemfile is that with new rubies always coming out, you've got to be updating all your Gemfiles all the time.
In general, the last couple years of ruby releases have all been very backwards compatible, limiting the need to be sure you're using an exact version of ruby, most recent code will run on the most recent ruby, even if it was originally written for an older one.
I don't believe either feature lets you specify a range of ruby versions, like 2.2.*
or what have you.
With either/both features, use them only if you need them or find them useful, you don't have to use either, and it's fine (if annoying) to use both, if you need what both do.
Since a Gemfile is live ruby code, you could theoretically have your Gemfile read your .ruby-version
file and automatically use that value as the Gemfile ruby
value. If you wanted to use both, and "don't repeat yourself" with it. I don't know if that's a common thing to do, I just thought of it. But it should work fine.
I think it's better to avoid listing the same information twice unless there's a good reason - i.e., keep it DRY.
You can store the ruby version in ".ruby-version", and then in the Gemfile do something like this:
ruby File.read('.ruby-version').strip
I originally posted the following, which collimarco then shortened into the above:
ruby File.open('.ruby-version', 'rb') { |f| f.read.chomp }
If you do this, then whenever you change .ruby-version the Gemfile will magically do the same.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With