clarification on rvm and switching between rails - ruby-on-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.

Related

Do I have to install Rails on every new project?

This is a beginner-level question.
I'm using Ubuntu 12.04
I copied a project (created on Rails 4 using the rails new command) from Dropbox to my local environment, where I have previously install Rails 4 and up-to-date Ruby and RVM, went to project's directory, typed rails server and got
The program 'rails' is currently not installed. You can install it by typing:
sudo apt-get install rails
I ran gem install rails instead.
Will I have to run gem install rails on every project's directory? I thought the Rails install was a general and accessible on my whole environment.
The project was created using the same Ruby version, but on a MacOS X system.
The project is a static web brochure and has no database configuration.
Thank you in advance.
Make sure you're using the correct version of Ruby - the same version that you'd installed Rails into - with rvm list.
You likely have two of them (since you have such an issue) - the system Ruby and the RVM-installed Ruby. And likely RVM didn't engage and hook up the correct path to the rails executable, thus the error.
This should fix the issue:
rvm use whatever-ruby-you-had-installed-rails-into
Where whatever-ruby-you-had-installed-rails-into is a string like ruby-2.1.0-p0 taken from the rvm list output.
To make RVM retain Ruby version for the project.
echo whatever-ruby-you-had-installed-into >.ruby-version
in your project's path.
So after a few hours of testing, reproducing the problem, and reading (the other answers inclusive) I got the solution as follows:
Short answer: No. Rails needs to be installed only once.
Long answer: This problem occurred because of a default setting on Terminal that prevents the system from using RVM installations of ruby and rails. The solution is to integrate RVM with gnome-terminal as described in the RVM website.
With terminal window active, go to the menu at the top bar
Edit > Profile Preferences > Title and Command tab
Check the Run command as a login shell box
Restart Terminal and make sure your gemset and ruby version are set
rails server should now work as expected (you might be prompted to run bundle install before Rails can actually run fine, follow the promtp).
I am still learning to work with Ruby on Rails, so any inputs, clarifications, or additional information on the issue is more than welcome.
You don't have to install Rails on every project, but the gems that you need for that project.
With bundle install you install all the gems that you specify in Gemfile.
If you want to avoid reinstall the gems every time you change project, I suggest you to have a better look to RVM: it has got an opt called gemset (https://rvm.io/gemsets), if you use it you just need to switch your gemset:
rvm gemset use yourgemset
I hope it can help you.

can't install new Rails app; RVM 'global' gemset missing from main directory but visible in app sub-directories

When I try to create a new Rails app in the directory in which I keep all my Rails apps, I get the following error:
Rails is not currently installed on this system. To get the latest version, simply type:
$ sudo gem install rails
You can then rerun your "rails" command.
I've recently been working with an RVM tutorial, so I thought it might have something to do with a gemset I had created. I typed 'rvm gemset list' and found the following:
gemsets for system (found in /Users/rickthomas/.rvm/gems/system)
=> (default)
*
But the weird thing is, I cd'ed into the directory of one of the apps, and ran the same command, and found this:
gemsets for ruby-1.9.3-p429 (found in /Users/rickthomas/.rvm/gems/ruby-1.9.3-p429)
=> (default)
global
When I run the 'rails --version' command in the main directory, I get the message to run 'sudo gem install rails', but when I run the same command from within the app directory, I get this:
Rails 3.2.12
Kinda confused why I all of a sudden can't create a new Rails app, since the last one I created was this morning, a day after I finished the RVM tutorial, and didn't make any gemset changes since then.
It looks like your "system" ruby doesn't have the Rails gem installed. You probably don't want to be using the system ruby anyway. How about you try this:
rvm use 1.9.3 # switch to your Ruby 1.9.3 that the other app used
gem list # make sure rails is listed
gem install rails # (only if rails was not listed)
rails new myapp
There is nothing weird about the "weird thing" you observed. When you cd into a directory, RVM looks at files like .rvmrc, .ruby-version, and .ruby-gemset in that directory and it automatically changes your environment to match. You can run "rvm info" to see what kind of environment you are currently in (I usually focus on the GEM_HOME and GEM_PATH variables). In this case, cd'ing into your Rails app directory caused RVM to switch you to Ruby 1.9.3, and that's the Ruby where you had the rails gem installed. Seems normal to me.

Ruby On Rails 3.2.13 - Using Different Gemsets For Rails Applications

I currently have several Rails applications running version 3.2.13 that use Ruby 1.9.3. I plan to eventually upgrade my current applications to Rails 4.0 then upgrade Ruby to 2.0. I need to time the conversion to Ruby 2.0 carefully since from my understanding Phusion Passenger will only handle one version of Ruby without some nose bleeding solutions which I do not plan to attempt to implement at this point.
I currently use one gemset for all my Rails applications. I would like to convert my Rails applications one by one from 3.2.13 to the current version of Rails 4.0 at some point. When I have tried to update one of my applications to a newer version of Rails I was told I had to do a update rails command.
What I want to do is to be able to run some of my applications using Rails 3.2.13 and others using Rails 4.0 until I am sure they will all run properly under Rails 4.0. Once I do this I will review the differences between Ruby 1.9.3 (if any) and upgrade all of them to use Rails 2.0. At this point I understand that I would just create the gemset for 2.0.0 or whatever the latest stable version of Ruby 2 is.
I have done web searches and checked the RVM website. I understand how the gemsets are assigned to the version of Ruby you want to run. However I'm not seeing anything about using gemsets with the same version of Ruby but using different versions of Rails or other combinations of gems on the same machine for different applications. Can this be done?
Any help would be appreciated.
Take a closer look! ;)
First, create a new gemset with a name corresponding to your project
https://rvm.io/gemsets/creating/
ex: rvm gemset create project_name
Then create/edit .rvmrc file in project directory: rvm use 1.9.3#project_name
One pitfall is that if you execute following commands
cd some_project
cd ../other_project
and other_project doesn't have gemset specified you'll stay in some_project gemset. To avoid that you can create .rvmrc file with default gemset in your "projects" directory (if you have one)
Project Folder
|___Gemfile
|__.ruby-gemset
|__.ruby-version
Gemfile with all the required gems mention in your project folder
.ruby-gemset should have gem set name like sample-gemset
.ruby-version file should have specific ruby version (e.g 2.0)
rvm gemset list
it will show gem set created with sample-gemset and do the
bundle install
which will install all the specific gems for this project under sample-gemset,
same you can do for other project to create other gem set, in this way you can maintain different rails/gems and ruby version for different projects with rvm.
Your Gemfile.lock nails down which version of every gem you use - you don't need to worry about gemsets.
bundle install will always install the correct versions and your app will always use the versions in Gemfile.lock, even if there are other versions floating around

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.

How do you use multiple rails versions with rbenv?

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.

Resources