Setup Ruby on Rails local development with lintting(rubocop) and language server(solargraph) easy and fast using vscode’s devcontainer

Leon. Z
4 min readDec 12, 2022

--

As a vscode user When I got my hands on ruby, I struggled quite a bit setting up the local development environment. As my team wasn’t using any sort of formatter and lintter with their IDE/editor at the time when I joined, instead, they were rely on the rubocop validation process on CI/CD, I figured I have to find a way to unify this for the team. or at least for the sake my own developing efficiency.

To allow everyone to setup the development environment with one click and guarantee the consistent coding standard and experience, I believe vscode’s devcontainer is an ideal choice, it allows you to setup the vscode configuration, extensions, postbuild commands, parameters within one single json file.

Below I will walk you through the steps of setting up the devcontainer, I also provided all the configuration in a gist at the end of this doc:

  • Make sure your VScode installed the Remote Development Plugin
  • Create an .devcontainer folder in the root directory of your project, and put the configuration below inside as devcontainer.json. As was using M1 Macbook, I choose bullseye variant of my ruby versions, please adjust base on your situations. I have also included some necessary vscode extensions in the config to be preinstalled after building the container, as well some personal recommended ones, such as github copilot and cspells, feel free to modify it as your preference.
//.devcontainer/devcontainer.json
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.224.2/containers/ruby-rails
{
"name": "Ruby on Rails (Community)",
"build": {
"dockerfile": "Dockerfile",
"args": {
// Update 'VARIANT' to pick a Ruby version: 3, 3.1, 3.0, 2, 2.7, 2.6, 2.5
// Append -bullseye or -buster to pin to an OS version.
// Use -bullseye variants on local on arm64/Apple Silicon.
"VARIANT": "3-bullseye",
"NODE_VERSION": "16"
}
},
"runArgs": ["--network=host"],
"postAttachCommand": "bundle install --gemfile=.devcontainer/Gemfile",
// Set *default* container specific settings.json values on container create.
"settings": {
"ruby.lint": {
"rubocop": {
"lint": true,
"rails": true,
"configFilePath": ".rubocop.yml"
}
},
"ruby.format": "rubocop",
"files.associations": {
"Gemfile": "ruby"
},
"[ruby]": {
"editor.defaultFormatter": "misogi.ruby-rubocop",
"editor.formatOnSave": true
},
"[yaml, yml]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
},
"prettier": {
"configPath": ".devcontainer/prettierrc.yaml"
},
"cSpell.enableFiletypes": ["ruby", "slim"],
"cSpell.ignorePaths": [".devcontainer"],
"cSpell.ignoreRegExpList": ["/gkc_hash_code.*/g"]
},

// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"rebornix.ruby",
"wingrunr21.vscode-ruby",
"castwide.solargraph",
"misogi.ruby-rubocop",
"hridoy.rails-snippets",
"ninoseki.vscode-gem-lens",
"eamodio.gitlens",
"kaiwood.endwise",
"esbenp.prettier-vscode",
"streetsidesoftware.code-spell-checker",
"GitHub.vscode-pull-request-github",
"karunamurti.rspec-snippets",
"2gua.rainbow-brackets",
"oderwat.indent-rainbow",
"GitHub.copilot"
],

// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],

// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "ruby --version",

// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "vscode",
"features": {
"git": "latest"
}
}
  • Create the Dockerfile
# .devcontainer/Dockerfile
# [Choice] Ruby version (use -bullseye variants on local arm64/Apple Silicon): 3, 3.1, 3.0, 2, 2.7, 2.6, 3-bullseye, 3.1-bullseye, 3.0-bullseye, 2-bullseye, 2.7-bullseye, 2.6-bullseye, 3-buster, 3.1-buster, 3.0-buster, 2-buster, 2.7-buster, 2.6-buster
ARG VARIANT=3-bullseye
FROM mcr.microsoft.com/vscode/devcontainers/ruby:0-${VARIANT}

# Install Rails
RUN gem install rails webdrivers

# RUN bundle install
# Default value to allow debug server to serve content over GitHub Codespace's port forwarding service
# The value is a comma-separated list of allowed domains
ENV RAILS_DEVELOPMENT_HOSTS=".githubpreview.dev"

# [Choice] Node.js version: lts/*, 16, 14, 12, 10
ARG NODE_VERSION="lts/*"
RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"
  • Gemfile for the necessary gems (rubocop, solargraph .etc)
# .devcontainer/Gemfile

source "https://rubygems.org"

gem "rubocop", "1.39.0"
gem "rubocop-performance", "1.15.1"
gem "rubocop-rails", "2.17.2"
gem "solargraph"
  • prettier configurations for non ruby files (yaml, json .etc)
# .devcontainer/prettierrc.yaml
singleQuote: true
  • Finally in your vscode’s command palette (cmd+shift+p), reopen your workspace in container:

Now VScode tells you what’s wrong with your code and run the lintting automatically on save.

Highlights the lint error
Shows detailed error message

Here I created a gist contains all above configurations, simply clone and put all files in a .devcontainer folder in the root directory of your project, you should be good to go!

Have fun coding.

--

--

Leon. Z

Built in US, Struggling in Japan, Software Engineer