Engineer's Guide To Windows: Ruby on Rails
Tags: programming, windows, debian, wsl
Published: 2021-03-09 00:21:52

---
title: Engineer's Guide To Windows: Ruby on Rails
published: true
date: 2021-02-23 18:00:00 UTC
tags: programming,windows,debian,wsl
canonical_url: https://www.ramimassoud.com/2021/02/23/code-with-wsl-ruby-rails
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m5f19d1uvy1kcz3ykjkv.png
series: Engineer's Guide To Windows
---

As I've [mentioned](https://dev.to/ramimassoud/engineer-s-guide-to-windows-wsl-5baa), 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.

```bash
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](https://docs.github.com/en/github/authenticating-to-github/managing-commit-signature-verification) to get that sweet verified badge in GitHub.

![github-verified](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2sq769ewor7ilgidc719.png)

Installing `keychain` is new for me. It's a handy tool to manage your ssh and GPG keys. Once installed, add 
```bash
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

<figure>
![long-journey-ruby-scene](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ko0uop3hd32a24fwb74y.jpg)
  <figcaption>Photo by [Matt Howard](https://unsplash.com/@thematthoward?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/journey?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText) with some help from [Matz](https://www.ruby-lang.org/en/about/logo/)</figcaption>
</figure>

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](https://github.com/rbenv/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](https://github.com/rbenv/rbenv-installer#rbenv-installer) script (after reading the source over).

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

Now rbenv and [ruby-build](https://github.com/rbenv/ruby-build#readme) 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!

```bash
$ 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](https://gcc.gnu.org/) 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.

```bash
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](https://github.com/ged/ruby-pg), and `g++` for the [sassc gem](https://github.com/sass/sassc-rails).

### 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](https://github.com/nodenv/nodenv), which, nicely enough, is the Node version of rbenv. 😎

It even has a similar installation process.

```bash
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

![hold-all-these-prereqs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ryv06aaio89xxo0qyauq.jpg) 

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:

```bash
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.

```bash
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.

```bash
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](https://brew.sh/), 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](https://serverfault.com/a/325596).

```bash
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](https://www.postgresql.org/docs/13/auth-trust.html). This can be done by updating `/etc/postgresql/11/main/pg_hba.conf` to have `local` and `host` use `trust` for authentication.

```shell
# "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

```bash
gem install bundler
```

#### Rails Itself 🤔

For completeness sake, [installing the Rails gem](https://guides.rubyonrails.org/getting_started.html#creating-a-new-rails-project-installing-rails-installing-rails) 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

```bash
gem install rails
```

### Enjoy Building A New Application

```bash
$ 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/webpacker@5.2.1 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.

<figure>
![fireworks](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vxv9cmyangumkz8g056k.jpg)
  <figcaption>Photo by [Mike Enerio](https://unsplash.com/@mikeenerio?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/fireworks?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText)</figcaption>
</figure>