How do you use multiple rails versions with rbenv? - ruby-on-rails

Is it possible to use multiple versions of rails using rbenv (e.g. 2.3 and 3.1)? This was easy with gemsets in rvm, but I'm wondering what the best way is to do it now that I've switched to rbenv (also, I'm looking for a way to do it without rbenv-gemset).

not sure if you got an answer to this, but I thought I'd offer what I did and it seemed to work.
So once you get rbenv installed, and you use it to install a specific ruby version, you can install multiple versions of rails to for that ruby.
STEP 1. Install whatever version(s) of rails you want per ruby version
% RBENV_VERSION=1.9.2-p290 rbenv exec gem install rails --version 3.0.11
By using the "RBENV_VERSION=1.9.2-p290" prefix in your command line, you're specifying which ruby rbenv should be concerned with.
Then following that with the "rbenv exec" command, you can install rails. Just use the version flag as in the example to specify which version you want. Not sure if you can install multiple versions in one shot, but I just run this command as many times as needed to install each version I want.
Note: This will all be managed within your rbenv directory, so it's perfectly safe and contained.
STEP 2. Build a new rails project by specifying the rails version you want.
% RBENV_VERSION=1.9.2-p290 rbenv exec rails _3.0.11_ new my_project
STEP 3. Don't forget to go into that project and set the local rbenv ruby version.
% cd my_project
% rbenv local 1.9.2-p290
Now if you want to delete this project, just delete it as normal.
If you want to delete / manage a rails version from rbenv gems, you can use regular gem commands, just prefix your command line with:
% RBENV_VERSION=1.9.2-p290 rbenv exec gem {some command}
And of course, you can delete a complete ruby version and all its shims, etc that are managed within rbenv pretty easily. I like how self contained everything is.
Hope this helps.
For reference, this is a pretty good walk through of at least some of this stuff:
http://ascarter.net/2011/09/25/modern-ruby-development.html

There is a rbenv plugin called rbenv-gemset which should behave similar to the rvm gemset-command but since rbenv was never intended to work this way, I haven't tried it.
I usually manage Rails versions with Bundler as Nathan suggested in the comments of one of the other answers. I create a Gemfile with my desired Rails version, run bundle install, create the Rails application, let it replace the Gemfile and let Bundler take over:
mkdir my-rails-app
cd my-rails-app
echo "source 'https://rubygems.org'" > Gemfile
echo "gem 'rails', '3.2.17'" >> Gemfile
bundle install
bundle exec rails new . --force --skip-bundle
bundle update
If you want more detail, I wrote an article on my blog about it.
Hope it helps!

If you have setup ruby using rbenv the following will work.
Installing rails, the latest version (7.x as of Oct 2022)
gem install rails -v 7.0.2.4
# Find exe
rbenv rehash
To create a rails project with the latest rails version,
rails new project_1
This will create a rails application with the latest version, to verify we can see the rails version in the Gemspec file (or) see the logs during the installation,
Installing rails, 6.x.x.x version
Assuming we are going to install rails 6.0.4.8, then issue the following commands
gem install rails -v 6.0.4.8
rbenv rehash
Now, to create a rails project with 6.0.4.8 version (which is installed previously), specify the rails version along with the rails command.
rails _6.0.4.8_ new project_2
This will create a rails application with the 6.x version, to verify we can see the rails version in the Gemspec file (or) see the logs during the installation,
Other notes
Similarly, we can manage any no of rails versions in any number of
projects.
rbenv rehash Installs shims for all Ruby executables known to
rbenv
In this approach, you don't need to set or modify any ruby
environment variables.
You don't need to modify Gemspec file by yourself.
The instructions work as of Oct 2022.

Related

Does Rails need to be installed as a system gem?

In every setup describing a configuring an environment with rbenv and Bundler, the instructions are always to install bundle as a system gem, using gem install bundler. Often, they'll also recommend rbenv-bundler rbenv plugin, but the maintainers of rbenv discourage this.
What's not described is how to install Rails. Initializing a new Rails project creates a basic Gemfile for bundler. However, in order to initialize a Rails project, one needs to have Rails installed. It seems weird and even wrong to make a directory, write a basic Gemfile that includes Rails, run bundle install, and then initialize Rails to the current directory. In fact, I doubt that would even work well, if it worked at all.
So, does Rails need to be installed as a system gem with gem install rails? If so, how does one manage multiple versions of Rails, particularly with rbenv?
It totally makes sense to NOT install rails as system gem.
Without messing up rbenv or other ruby version manager you use, below are brief steps to create (initialize) a new Rails app from a directory with a Gemfile:
mkdir rails_app
cd rails_app
vi Gemfile # Edit it to include a rails version you need
bundle --path vendor # Wait for bundler to finish
bundle exec rails new ./
The last step would ask: Overwrite /path/to/rails_app/Gemfile? (enter "h" for help) [Ynaqdh]. Input y to get the default Rails Gemfile content.
Note: the above steps specify the local vendor directory (inside the rails app folder) to avoid installing gems to system global scope.
Answer is no, you don't install rails as system gem. Create a project folder, add .ruby-version file and add the ruby version you would like in this file i.e. 2.3.0. rbenv uses the version specified in this file and it won't be system's ruby.
Now you can do gem install bundler from this directory and create Gemfile and add your rails version. Now run bundle install and roll it on the tracks of RAILS.....
Force rails to vendor gems.
$ mkdir foo
$ cd foo
$ bundle config --local path vendor
$ rails new .

Upgrading Rails with rbenv

I want to upgrade an application to the latest Rails version (4.2).
I'm using rbenv as a version manager.
Can I just install the rails 4.2 gem without affecting my other Rails applications?
thanks for your advice,
Anthony
rbenv is a tool for managing different ruby versions in your system. While it's possible to install different rails versions for a single ruby version installed using rbenv, installing rails is bundler's job.
Quoting from a really good answer by Nathan from here, where it's explained how would one install different rails versions for a single ruby version (go and upvote the answer if you find this helpful) :
So once you get rbenv installed, and you use it to install a specific
ruby version, you can install multiple versions of rails to for that
ruby.
STEP 1. Install whatever version(s) of rails you want per ruby version
% RBENV_VERSION=1.9.2-p290 rbenv exec gem install rails --version
3.0.11
By using the "RBENV_VERSION=1.9.2-p290" prefix in your command line,
you're specifying which ruby rbenv should be concerned with.
Then following that with the "rbenv exec" command, you can install
rails. Just use the version flag as in the example to specify which
version you want. Not sure if you can install multiple versions in one
shot, but I just run this command as many times as needed to install
each version I want.
Note: This will all be managed within your rbenv directory, so it's
perfectly safe and contained.
STEP 2. Build a new rails project by specifying the rails version you
want.
% RBENV_VERSION=1.9.2-p290 rbenv exec rails _3.0.11_ new my_project
STEP 3. Don't forget to go into that project and set the local rbenv
ruby version.
% cd my_project
% rbenv local 1.9.2-p290
And here is Michael's blog post explaining how one can manage different rails versions installed this way. You would basically modify the Gemfiles and specify the version you want, and then let bundler take care of installation. Here's the answer where he talks about this.
Also, I haven't tried rbenv-gemset but it looks promising at a glance. I would use it if I were you, at least to try it once. :)

clarification on rvm and switching between rails

following http://railsapps.github.io/installrubyonrails-mac.html , I encounter the following commands
rvm use ruby-2.1.3#rails4.1 --create
gem install rails # installs the latest rails version
rails -v # returns 4.1.6
however, I can also do the following, which would add rails version to 4.0.8
rvm use ruby-2.1.3#rails4.0 --create
gem install rails --version=4.0.8 # installs the latest rails version
rails -v # returns 4.0.8
What is the point of this? Somewhere in the text it's said that this method is to prevent global gem-set and instead install rails based on project-specific gemsets? What does that even mean?
And this is the instructions on how to create a new rails project
$ mkdir myapp
$ cd myapp
$ rvm use ruby-2.1.3#myapp --ruby-version --create
$ gem install rails
$ rails new .
why not just call rails new myapp? The text says it's to "create a project-specific gemset", but I have no idea what that means. Wouldn't this just install rails 4.1.6 (newest version) ? why not just install rails 4.1.6 globally in the first place then?
Imagine you are a Rails developer in a company that has been doing Rails apps for the last 4 years. You have apps on Rails 2, Rails 3, Rails 4 - as new versions come out, you upgrade your toolset because, why not? Each new version is better.
However, they are not downward compatible. The Rails 2 app will not work with Rails 4.1. What if you are asked to urgently debug the Rails 2 app while hacking on Rails 4 one? Uninstall global Rails, install Rails 2, make the hack, then uninstall Rails 2 and reinstall the new one again, just so you can run the tests for your one-line bug fix?
That's where gemsets come in. You have environment per-application so that each application can be run self-sufficiently, with no versioning conflicts.
If you don't envision such scenarios of version conflict on your machine (i.e. if you can only imagine working on one project), gemsets are completely irrelevant.
EDIT after some confusion still in comments :) Let's go step by step, see what happens exactly.
$ mkdir myapp
$ cd myapp
You're now in an empty directory.
$ rvm use ruby-2.1.3#myapp --ruby-version --create
rvm creates a new gemset, named ruby-2.1.3#myapp, which will be run with Ruby 2.1.3. As a consequence, you have a new directory at ~/.rvm/gems/ruby-2.1.3#myapp, where your gemset will be. You also have two new files in your previously empty myapp directory: .ruby-version (which contains a single line saying ruby-2.1.3) and .ruby-version (containing the line myapp). These two lines are read by rvm every time you enter the myapp directory: it sets the current Ruby and gemset for you.
$ gem install rails
Having recognised that the current gemset is now ruby-2.1.3#myapp, the gem install command will download the newest rails gem, as well as all its dependencies, and put them in your gemset directory (~/.rvm/gems/ruby-2.1.3#myapp/).
$ get install rails --version=4.0.8
If you try this, it will dutifully install Rails 4.0.8, but since you have a newer version in your gemset and your application is not specifically having any requirements, the newer one will take precedence. This is normally not what you want; and anyway, there is rarely a reason to develop a project to comply with two different versions of a library (unless you're developing a library or a plugin; that's a different story).
$ rails new .
rails is actually executing ~/.rvm/gems/ruby-2.1.3#myapp/bin/rails. If you were not in myapp directory, linked to the gemset, this command would have failed (if you didn't have Rails installed in the global environment), or executed globally installed Rails (if you did).
So, it's not really designed to have two versions of Rails simultaneously in the same project. But when you make another project, with another gemset (say, ruby-2.1.3#myotherapp), you could have a different version of Rails while you're there. The version automagically changes just based on which directory you cd into.

Rails version stuck at 2.3.5 how to update to 3.x

Hi there thanks for looking into this.
after a clean install of Linux ubuntu 10.10 i tried to re-install rails.
after doing sudo gem install rails, I can see I am returned version 3.2.3 of rails
But after generating a new project i couldn't find my gemfile so i tried ruby -v which returns 2.3.4 wich is odd since I know I got the latest.
Also when trying sudo gem update --system I get an error because I might override system files. any solution here?
I'd recommend using rvm to manage your ruby sets -- as well as defining gemsets for each project that will allow you to make sure each project has just the gems it needs.
Here's a link to the rvm installation instructions (they should work with ubuntu):
https://rvm.io/rvm/install/
Here's some info on basic use of gemsets with rvm:
https://rvm.io/gemsets/basics/
Also, when using rails 3+, you should make a practice of typing bundle exec rails -v -- that way you'll use the gems defined for the project you're in.
Can you try typing bundle exec rails -v and letting us know what you see?

rbenv: Surviving without gemsets

TL;DR
Don't bother with gemsets; multiple versions of a gem may be installed concurrently.
When necessary, specify which version to execute using $ gem-based-binary _version_ args notation.
Use bundle exec when you have a Gemfile specifying the version.
gem install rails -v 3.2.13
rails _3.2.13_ new Project2
cd Project2
bundle exec rails server
UPDATE: 2015-06-04
I wrote this question three years ago. Partly, it was based on a false assumption, and partly the situation has changed since then. With appreciation to #indirect for his original answer, I want to call attention to #kelvin's newer (less upvoted) answer, summarized above.
My false assumption: Only a single version of a gem could be installed at a time, hence the need for gemsets to isolate the namespace. Not true. Multiple versions of a gem may be installed concurrently. The most recent one will be used when invoked from a command line, unless you have a Gemfile specifying the version constraints and invoke the command via bundle exec, or specify the version as its first argument.
See also How can I call an older version of a gem from the commandline? re: the underscore-version notation.
Original question:
I have multiple projects going on using different versions of Rails. I have a workflow (described below) for creating projects using specific versions of rails, and keeping the projects isolated from each other. I'd like to experiment with other workflows, in particular, using rbenv instead of RVM, but it's not clear how to do so.
QUESTION: What is the best current practice for creating multiple rails projects, each using a different version of rails, when making use of rbenv and bundler, as opposed to rbenv-gemset or rvm?
USE CASE: I have two rails projects, called ProjectA and ProjectB. ProjectA is developed using one version of rails ("RailsA"), whereas ProjectB uses a different version ("RailsB"). How do I manage having both versions installed?
THE GEMSETS APPROACH: When I first started with Rails development, I used RVM. In addition to supporting multiple, concurrent installations of ruby, RVM supports having multiple Named Gem Sets. Each project has its own independent collection of gems (including rails itself) called a gemset:
rvm gemset create RailsA
rvm gemset use RailsA
# RailsA. Note: My question is not version-specific.
gem install rails --version 3.0
rails new ProjectA
cd ProjectA
rvm --rvmrc use `rvm current`
vi Gemfile
bundle install
cd ..
## Now do the same for ProjectB
rvm gemset create RailsB
rvm gemset use RailsB
gem install rails --version 3.2
rails new ProjectB
cd ProjectB
rvm --rvmrc use `rvm current`
vi Gemfile
bundle install
Note: The very creation of the project folders should be done (IMHO) by a rails new command using the desired version of rails, since the skeleton files change from version to version. (Perhaps I should revisit this premise?)
THE BUNDLER APPROACH: I've been playing with using rbenv instead of RVM, but I don't understand the workflow as clearly. In the README.md, Sam Stephenson writes that "rbenv does not ... manage gemsets. Bundler is a better way to manage application dependencies." There is a plugin (rbenv-gemset) for getting the same results as rvm's gemsets, but Sam clearly favors using Bundler instead. Unfortunately, he doesn't elaborate on what the workflow would look like. Even the Bundler website doesn't explicitly connect all the dots of how to isolate one project from another. Several blogs and gists come to the rescue, suggesting the following ~/.bundle/config file:
---
BUNDLE_PATH: vendor/bundle
(BTW, I'm not sure what the "---" is about. The docs make no mention of it and it doesn't seem to make a difference.)
This effectively gives each rails project its own gemset, storing the gems in ProjectX/vendor/bundle/. In fact, rails itself will be (re-)installed there, making the project completely independent of the rest of my environment, once I run bundle install.
But the elephant in the room is the chicken-and-egg problem of creating the rails project folder in the first place!! In order to create the ProjectA folder using RailsA, I need to install rails (and its numerous dependencies) first. But when I want to create ProjectB, I must then switch to using RailsB. Without gemsets, I must do some serious upgrading/downgrading. Not cool.
A possible solution is simply not to worry about what version of rails I use to create the ProjectX folder. If I then use rails 3.0 to create a 3.2 project, I could just manually create the app/assets tree. But that just irks me. Ain't there a better way?
Most people solve this by installing the rails gem first via gem install rails. If you refuse to do that for some reason, you can opt out of the automatic bundling that Rails attempts to do for you. This will work completely regardless of your ruby management system.
mkdir myapp
cd myapp
echo "source :rubygems" > Gemfile
echo "gem 'rails', '3.2.2'" >> Gemfile
bundle install --path vendor/bundle
bundle exec rails new . --skip-bundle
When prompted, type "y" to replace your Gemfile with the default Rails one (or not, as you prefer). Then, once it's done:
bundle install
You're done, and you have boostrapped a new rails app with the version of your choice without installing the rails gem into rubygems.
Suppose you have rails 3.1.0 installed, but you want to create a new project using rails 3.2.13 which is not installed.
Let's say you want the new project to be in ~/projects/Project2.
gem install rails -v 3.2.13
cd ~/projects
rails _3.2.13_ new Project2
This will create the Gemfile for you, locked to the version of rails you specified on the command-line.
I deliberately omitted the idea of keeping a separate copy of gems for the new project, because that goes against the Bundler philosophy, which is to have all gems installed in one place. When you run rails, Bundler will pick the correct gem versions automatically from that central location. That means a project can share gems instead of installing a fresh copy for itself. (Note, however that each version of ruby you install will have its own gems. This is a good thing because native extensions likely won't work across ruby versions.)
You do have to be a bit more aware, because most commands, like rake, will load the newest version of rake that you have installed. You'll need to run bundle exec rake ... to make sure the correct version is loaded. Usually I'll run bundle exec for all commands except rails. You can create an alias to make it shorter (I use bex). To automate this with gem executables, you can use rbenv-binstubs, but you still have to be aware that running non-gem executables like ruby and irb won't automatically use the Gemfile.
Sidenote: rails new will run bundle install, which will check for the newest version of the dependencies. If you want bundler to try to use currently installed gems that satisfy the dependency requirements, you can skip the bundle install with rails new --skip-bundle, then run bundle check in the app dir.
Sidenote 2: suppose you want to use a ruby version for Project2 (e.g. 2.1.8) that's different from the default (e.g. 2.3.0). In that case, running gem install as specified above will install the gems under 2.3.0, which is a waste of time because you'll need to install the gems again under 2.1.8. To solve that problem, you can force the commands to use the preferred version via environment variable:
RBENV_VERSION=2.1.8 gem install rails -v 3.2.13
cd ~/projects
RBENV_VERSION=2.1.8 rails _3.2.13_ new Project2
echo 2.1.8 > Project2/.ruby-version
You could use rbenv shell to set the variable, but I only recommend that if you don't want rbenv to auto-switch based on .ruby-version files for the duration of that shell. It's very easy to forget that you have the variable set, and when you cd to a different project, it won't be using the version you expect.
There's a good recent post on exactly the topic of gemsets / bundler here http://rakeroutes.com/blog/how-to-use-bundler-instead-of-rvm-gemsets/ Good background you can apply to your rbenv setup.

Resources