Engineer's Guide To Windows: Ruby on Rails

Published in Programming on

As I've mentioned, I primarily work with Ruby on Rails applications. So it's fairly important that I can work with one on my sweet new WSL setup.

Mixed Bag of Prerequisites

Unlike a more standard Debian or a fresh macOS install, a clean WSL Debian install has a very minimal set of tools installed. So before getting into anything strictly Ruby or Rails related, I need to install some common tools I end up reaching for to accomplish all sorts of work, including getting a Rails dev environment setup.

sudo apt install ssh git man-db curl gnupg2 wget keychain

Nothing here should be too controversial to anyone who has worked in Unix-like systems before.

I was a little surprised that I needed to install the man database, but sure πŸ€·β€β™‚οΈ. Installing ssh, git, curl and wget are reasonable basics to have on a Linux system and are required to install Ruby and Node through version managers. I use gnupg2 to sign my commits to get that sweet verified badge in GitHub.

Git commit on GitHub showing verified badge

Installing keychain is new for me. It's a handy tool to manage your ssh and GPG keys. Once installed, add eval `keychain --eval --agents ssh id_rsa` to .bashrc/.bash_profile, then enjoy not having to type a passphrase every time you run a GPG or ssh command!

The Journey to Install Ruby

Winding mountain road to a Ruby

Photo by Matt Howard on Unsplash with some help from Matz

It's possible to grab Ruby (or Node, for that matter) versions from the Debian package manager, but I don't believe that's the most common or recommended way to install them. I always end up needing multiple or unavailable versions for one reason or another, so I lean on rbenv to manage installing and switching between those versions.

Use rbenv to pick a Ruby version for your application and guarantee that your development environment matches production. Put rbenv to work with Bundler for painless Ruby upgrades and bulletproof deployments.

I chose to install rbenv with the rbenv-installer script (after reading the source over).

curl -fsSL https://github.com/rbenv/rbenv-installer/raw/master/bin/rbenv-installer | bash

Now rbenv and ruby-build should be installed; just don't forget to run rbenv init and follow the instructions to have the shell recognize and find Ruby binaries.

Theoretically, any version of Ruby should be installable at this point!

$ rbenv install 2.7.2
Downloading ruby-2.7.2.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.2.tar.bz2
Installing ruby-2.7.2...

BUILD FAILED (Debian 10 using ruby-build 20201225-2-g5de6d5f)

Inspect or clean up the working tree at /tmp/ruby-build.20201230170140.1599.9kPeZh
Results logged to /tmp/ruby-build.20201230170140.1599.log

Last 10 log lines:
checking for ruby... false
checking build system type... x86_64-pc-linux-gnu
checking host system type... x86_64-pc-linux-gnu
checking target system type... x86_64-pc-linux-gnu
checking for gcc... no
checking for cc... no
checking for cl.exe... no
configure: error: in `/tmp/ruby-build.20201230170140.1599.9kPeZh/ruby-2.7.2':
configure: error: no acceptable C compiler found in $PATH
See `config.log' for more details

Well, that's not good πŸ™ˆ.

After seeing that error message, I hoped that installing GCC would be enough, but of course, there were a bunch of libraries missing too! I'll spare writing out the half dozen tries it took me to get all of the necessary libraries installed and get to the point.

sudo apt install gcc libc-dev make libssl-dev zlib1g-dev libreadline-dev

Those are what's needed just for Ruby. For my Rails app, I also needed to install libpq-dev to compile the Postgres gem, and g++ for the sassc gem.

Installing Node

Like with Ruby, it's good to have a version manager for all your Node needs. My preferred version manager for Node is nodenv, which, nicely enough, is the Node version of rbenv. 😎

It even has a similar installation process.

curl -fsSL https://raw.githubusercontent.com/nodenv/nodenv-installer/master/bin/nodenv-installer | bash

Again, just like with rbenv, follow the post-install instructions to ensure the shell recognizes and finds the binaries. Hopefully, as for me, installing Node will be much less eventful than Ruby was.

Rails Prerequisites

Man holding a bunch of Rails dependency logos

There is no reasonable way I know to cover the possible variations of Rails setups here. For clarity and sanity's sake, I'll limit this guide to generating a brand new app. Even more narrowly, this is the command I want to work:

rails new mycoolapp --skip-turbolinks --skip-action-cable --webpack=stimulus --database=postgresql

Yarn

As long as Node was successfully installed, installing Yarn is a one-liner.

npm install --global yarn

Keep in mind that Yarn will be installed in the current Node version, so verify it's the expected one with nodenv version.

PostgreSQL

Postgres is my go-to database for any project. As of this writing, the primary version available in Apt is Postgres 11, but pulling from the Debian testing source will get Postgres 13 for bleeding-edge database fun. Thankfully, installing is straightforward. As I mentioned earlier, make sure libpq-dev has been installed at some point, so the pg gem will be able to compile.

sudo apt install postgresql libpq-dev

It will not likely be a revelation to those who have experience with later versions of Postgres or who have only worked with it through Homebrew on a Mac, but I ran into some additional steps I needed to run through to connect to the database. After Postgres installed, I didn't have a way to create users, databases, or even access it with psql. It turns out I had to bootstrap myself a user through the postgres (sometimes postgresql) system user.

sudo -u postgres createuser --createdb --pwprompt WHATEVERUSERNAMEYOUWANT

I prefer to always create a Postgres role that matches my Linux username since that's the default if you don't specify a role name when using psql.

There is another way to work with databases locally, though it might be a little iffy on security. If this is strictly for development purposes, I don't think it's much of an issue. When creating users, leave off --pwprompt and change the Postgres config to instead trust any local connections. This can be done by updating /etc/postgresql/11/main/pg_hba.conf to have local and host use trust for authentication.

# "local" is for Unix domain socket connections only
local   all             all                                     trust
# IPv4 local connections:
host    all             all             127.0.0.1/32            trust

After the configuration change, any user or app's local connections will connect with only a username, no password required.

Bundler

What would working in Ruby be without Bundler? As long as Ruby is installed, this is as easy as

gem install bundler

Rails Itself πŸ€”

For completeness sake, installing the Rails gem should be the last piece of the puzzle to run that command I mentioned at the start of this section. Grab it just like Bundler

gem install rails

Enjoy Building A New Application

$ rails new mycoolapp --skip-turbolinks --skip-action-cable --webpack=stimulus --database=postgresql
      create  README.md
      create  Rakefile
      create  .ruby-version
      create  config.ru
      create  .gitignore
      create  .gitattributes
      create  Gemfile
         run  git init from "."
Initialized empty Git repository in /home/username/mycoolapp/.git/
      create  package.json
      create  app
         run  bundle install

Bundle complete! 16 Gemfile dependencies, 72 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
         run  bundle binstubs bundler
       rails  webpacker:install
      create  config/webpacker.yml
Copying webpack core config
Copying postcss.config.js to app root directory
Copying babel.config.js to app root directory
Copying .browserslistrc to app root directory
The JavaScript app source directory already exists
  Copying binstubs
Installing all JavaScript dependencies [5.2.1]
         run  yarn add @rails/[email protected] from "."
yarn add v1.22.10
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
success Saved 594 new dependencies.
Done in 11.39s.
Installing dev server for live reloading
         run  yarn add --dev webpack-dev-server from "."
yarn add v1.22.10
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
success Saved 102 new dependencies.
Done in 4.35s.
Webpacker successfully installed πŸŽ‰ 🍰
       rails  webpacker:install:stimulus
      append  app/javascript/packs/application.js
Creating controllers directory
Installing all Stimulus dependencies
         run  yarn add stimulus from "."
yarn add v1.22.10
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
success Saved 5 new dependencies.
Done in 4.43s.
Webpacker now supports Stimulus.js πŸŽ‰

A compact version of the output, but now generating a new Rails application should succeed! Maybe take a break, grab some water and a snack, then get to work on building a great side project.

Photo by Mike Enerio on Unsplash