My Ruby Environment 2020

I saw an excellent post by Jacob Kaplan-Moss (blog) about how he sets up his Python environment. Setting up your development environment is confusing when you’re new to a language. There seem to be a number of virtual environment options, and it is difficult figure out the best path. His blog post My Python Environment was a huge help to me. So I mentioned him on Twitter (@jacobian) to thank him. He wrote me back and suggested I do the same thing for Ruby. I just started a new job, so it’s a perfect time to repay the favor.

My requirements are similar to @jacobian

  1. Manage multiple ruby versions so that I can work on projects that have different versions of Ruby. Ruby version can vary enough to be non-compatible, even across minor revisions (2.x to 2.y)
  2. Avoid using the system version. It rarely matches the version that I need when working on an application.
  3. Avoid dependency hell: manage each environment depending on the version of Ruby

The following instructions assume OSX Catalina.

Manage Multiple Ruby Versions

I use rbenv to manage different Ruby versions.

  1. Install HomeBrew using /bin/bash -c ... https://brew.sh/
  2. Install rbenv with HomeBrew on OSX: (instructions)
    1. Per the instructions: don’t forget to add eval "$(rbenv init -)" to your .bash_profile (.zshrc if you’re using z-shell)
    2. Installing rbenv will also install ruby-build. This is necessary, as ruby-build makes it easy to install different rubies.
    3. NOTE: A case could be made for RVM as well. From what I’ve seen most Linux production installations use RVM since it works better in a multi-user environment. But for my personal machine rbenv is cleaner and simpler than RVM.
  3. Install openssl with HomeBrew: brew install openssl
    1. ruby-build requires openssl when installing some of the more recent versions of Ruby
  4. Some helpful rbenv commands
    1. List all available Ruby versions: rbenv install --list-all
    2. Install a version: rbenv install <version name> (e.g. rbenv install 2.6.6)

Handle Dependencies

I like to “vendor” my gems as a way to prevent “dependency hell”. In other words, I like to keep a copy of the gem with the project, rather than storing all of the gems with the ruby version. Since I started vendoring gems, I rarely get into serious trouble with gem dependencies. It uses more space on your hard disk, because you are storing multiple copies of the same gem, but the benefits out-weigh the costs.

  1. Fine-grained version control using the Gemfile. Different versions of dependencies can be maintained within the same Ruby version.
  2. Gem analysis. I can go in and easily inspect the source code for a gem by viewing it in the <project root>/vendor directory. This is much easier than spelunking through the gem directory tree.

The easiest way to vendor gems is to create a few aliases. I have the following aliases created.

# Bundler
alias b="bundle"
alias bi="b install --path vendor"
alias bil="bi --local"
alias bu="b update"
alias be="b exec"
alias binit="bi && b package && echo 'vendor/ruby' >> .gitignore"

Now, when I’m in a project I’ll type bi rather than bundle or bundle install

Further more, I have a few Rails specific ones. It’s just more fun to type bake 🙂

# Bundler Rails
alias bails="be rails"
alias bake="be rake"
alias bspec="be rspec"

I you need more justification here is an excellent blog post on vendoring gems

Start a New Project

I typically use the following flow for any Ruby development (other than Rails).

  1. Create a new project folder and cd into it
  2. Create a .ruby-version file with the desired version of ruby. rbenv will evaluate this file when cd’ing into the directory and will automatically switch to the specified version of Ruby.
  3. Initialize bundler to help with dependency management. This will create a Gemfile. Bundler uses the Gemfile to determine with dependencies need to be installed.
  4. Add the necessary gems
  5. Install the gems
# Step 1
mkdir demo
cd demo

# Step 2
echo 2.6.6 > .ruby-version
cd .
ruby -v # verify

# Step 3
bundle init

For Rails development, I’ve started using this command:

rails new <app name>  \
—skip-coffee \
—skip-action-cable \
—database=postgresql \
—skip-sprockets \
—webpack
--skip-bundle

Then cd into the project directory and run bi. Skipping bundle lets you vendor the gems and prevents the gems from being installed into your Ruby version namespace.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s