Engineer's Guide To Windows: Ruby on Rails
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.
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
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
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.