Using specified version of rails when starting? - ruby-on-rails

I have multiple version of rails installed. But when I start the server with "rails s" it always uses the latest one. Is there a way to specify the version of rails (and all dependent gems) that should be used? (And how would I specify that in Pasenger?)
Yes, I could use RVM or similar - but this I would like to avoid.
Thanks in advance!

Phusion Passenger author here.
The version of Rails that is loaded does not depend on 'rails server', and also does not depend on Passenger. RVM also has got nothing to do with it.
It only depends on your Gemfile.lock, which locks down all gem versions in your project. If you want a different version of Rails, you need to modify your Gemfile to specify that exact version, and run bundle install to update Gemfile.lock.

You can't do that with rails server command. Every project depend from a GemFile. But you can create a bash script that will move a custom specify GemFile to the default GemFile then start the server.
vi /script/rails4_to_rails3
#/bin/bash
mv /opt/web/my_app/GemFile /opt/web/my_app/GemFile.rails4
cp /script/GemFile.rails3 /opt/web/my_app/GemFile
bundle install
rails s
I'm not a Passenger Expert but in my opinion it's impossible to.

Related

Safe way to upgrade Ruby versions and gemsets in Rails applications

I want to upgrade our Ruby version and a bunch of gems on our production website that we are currently running. We use RVM to manage our Ruby versions and gemsets.
I know how to install a new Ruby version using RVM and install gems in a gemset. I also understand that if I run bundle install it will install my gems into the Ruby version I am running the command from.
Is there some way to pre-create a Ruby version with a gemset in it and then swap my production site to use this new Ruby version and gemset? I know this can be done manually, but is there anyway to do it with a gemfile?
Yes, you can specify the Ruby version in the Gemfile:
source 'https://rubygems.org'
ruby '2.1.3'
This allows you to set the version that would be used if you deploy to Heroku, for example. Your question does not detail your production environment, so it's not clear if it can use the Ruby version in the Gemfile.
Locally, the app will run against whichever Ruby version is active with RVM. The only way to know if it will work is to run the specs against the new Ruby version. Your question did not mention specs, but if you have a complete set of specs then this is the proper way to find out if the new Ruby version will work.
You can install new versions of Ruby and gem sets all day long without it affecting a running application. Once an application is running, it continues running under the same version of Ruby the entire time.
You can have RVM install new Rubies, manipulate gemsets, etc., as long as you don't remove the version of Ruby the application needs. If the binary disappears your app might crash/lock-up if the system needs to load something that has been deleted.
This totally depends on your setup. I am anwsering for a Passenger/Apache setup.
With Passenger and Apache, you can set my PassengerRuby in the Apache Vhost file so it uses that particular version of Ruby, I would set it to your current ruby path and restart Apache like so:
PassengerRuby <path-to-ruby>
Then you you can install your new ruby version and gems, once you install everything you can change the PassengerRuby to the new ruby path and restart Apache. This should migrate your Ruby version smoothly, since you can always fallback to your old Ruby version.

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. :)

Why "Rails -v" and "Bundle exec rails -v" is different

I have staging and productions servers through AWS. After a certain point of time(I think it was after I upgraded ruby version to 2.1), my staging/production servers couldn't find rails so I had to ssh in and redownload Rails and Ruby, but now when I run "rails -v" it gives me 2.3.14, but when I run "bundle exec rails -v" I get the proper 3.2.16.
I'm guessing this is because of paths, but not entirely sure how to solve this. Some of the answers I found suggested changing the .bashrc and changing the $PATH variable, but wasn't exactly sure what to change it to.
This is my .bashrc:
#PATH=$PATH:$HOME/.rvm/bin # how it was before
PATH = $PATH:$HOME/.rvm/gems/ruby-2.1.0/bin #edited this just now to see if it works. it didnt..
bundle exec rails will use the rails version defined in your Gemfile. On the other hand, a simple rails will run the latest version available on your computer.
What probably happened is this:
you had a rails version from rvm that was the same as the one used in your Gemfile (3.2.16), so you were not noticing any difference. After upgrading ruby, you have to reinstall all gems you did install on your previous version. Otherwise it will fallback to the latest available, which can be the system version (ie. not from rvm). This may explain why you have such an outdated one.
Note that a proper bundle install will install all the gems required in your Gemfile and then will do the job for you.

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.

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