A common challenge I frequently see development teams struggle with is being able to easily switch to work on multiple projects and multiple versions of a project. In most fast paced development teams there is usually one core Rails (server) project, several supporting infrastructure (Resque, API, etc) projects, and a few smaller MVP projects. Each of these components of the stack will have multiple versions to manage through out the development/deployment lifecycle.
This challenge can easily be solved by following some development best practices.
The first step to deal with multiple projects and versions is to use Git. This will allow developers to manage multiple isolated repositories and create feature branches off the mainline. Git will get you 90% of the way there by allowing developers to simply clone whatever remote repo the need to work on locally and branch for development. Where things fall apart is if the projects use different Ruby versions, different Rails versions, and/or a feature under development is using different sets of Gems.
This where the second step is needed; to use Ruby Version Manager. RVM allows you to easily install, manage, and work with multiple ruby environments from interpreters to sets of gems. Most developers seem to see the benefit of using RVM to manage different Ruby versions or interpreters, but usually stop there. The real power of RVM is Gemsets. This is why I usually ask people I am pairing with the question:
Are you using Gemsets?
Gemsets are compartmentalized independent ruby setups that are separate and self-contained – from the system, and from each other. By using Git & RVM Gemsets developers can easily switch between any project and not have any conflicts. Let’s look at a few examples.
Starting a new project
$ mkdir cool_app $ cd cool_app $ rvm use ruby-2.2.3@cool_app_rails4.2.5 --ruby-version --create $ gem install rails $ rails new . $ echo "# Cool App" >> README.md $ git init $ git add README.md $ git commit -m "first commit" $ git remote add origin firstname.lastname@example.org:CarlosGabaldon/cool_app.git $ git push -u origin master
The above will create:
- New Gemset called cool_app_rails_4.2.5, RVM creates the following hidden files: .ruby-gemset and .ruby-version, these files will automatically switch RVM to correct ruby version and gemset when doing: cd cool_app
- New Rails application called cool_app
- New Git repository called cool_app
If you run the following command you will see the newly created Gemset
$ rvm gemset list gemsets for ruby-2.2.3 (found in /Users/carlosgabaldon/.rvm/gems/ruby-2.2.3) (default) => cool_app_rails_4.2.5 global
So whenever needing to work on this project you would simple cd into the project directory.
$ cd cool_app
RVM will automatically switch to the correct ruby version and Gemset (via .ruby-version and .ruby-gemset files) You can manually switch to the Gemset by running the following command:
$ rvm gemset use cool_app_rails_4.2.5
Working on an existing project
$ cd cool_app $ git checkout master $ git pull $ git checkout -b upgrade_to_rails_5.0.0.beta1 $ rvm use ruby-2.2.3@cool_app_rails_5.0.0.beta1 --ruby-version --create $ cd ../cool_app/
The above will:
- Switch to the master branch of cool_app
- Pull the latest code from the remote repo
- Create a new feature branch called upgrade_to_rails5.0.0.beta1
- Create a new Gemset called cool_app_rails_5.0.0.beta1, creating new hidden files: .ruby-gemset and .ruby-version
- Change out of the current directory then back in, this activates RVM to switch to the correct ruby version and Gemset (via .ruby-version and .ruby-gemset files)
Now while we are working on our new branch to upgrade our cool app to Rails 5. We are able to add and remove Gems as needed for the upgrade and know that we will not be impacting our mainline code and Gems. If we have to switch back to master to fix a bug we just run the following commands:
$ git checkout master $ cd ../cool_app/