A cleaner way to start Rails projects

There is a bit of background information required to set this article up: I like clean computer systems. In this context, it means only having the required applications or libraries installed. It keeps things simple. To accomplish this in the Ruby world, I have a ~/.bundle/config that contains BUNDLE_PATH: "vendor/bundle". This ensures all gems are placed in the same folder of the application using them, instead of the default of $GEM_HOME. I only have a handful of gems installed globally, majority being installed per application. One such gem that I previously always had installed globally, including many alternate versions, was Rails. No more!

Recently I have been spending a lot of time experimenting with containerization through Docker. Most of it has been to get an old Rails application (Rails 3.x and Ruby 2.x) running on the latest Apple silicon/ARM architecture powered hardware. During that time I learned a little something to prevent installing Rails globally, and instead only within the context of the application.

Create the folder to store your application’s source code, along with the Gemfile.

mkdir MyApp
cd MyApp
touch Gemfile
touch Gemfile.lock

Edit the Gemfile to include the source and Rails.

source 'https://rubygems.org'
gem 'rails', '~>6'

Install the gems.

bundle install

Finally, initialize the Rails project. This will use the local version of Rails that was specified in the Gemfile and now installed to MyApp/vendor/bundle. The --force will overwrite the current Gemfile and Gemfile.lock without a prompt. The name of the application will be the same as the folder.

bundle exec rails new . --force

That’s it! A gem list will show your global gems, of which Rails is nowhere to be seen. A bundle list will show all of the gems installed for MyApp, including Rails.

Why though? It’s a bit cleaner, I like it.