A picture of me

About me

I'm a full stack web developer.

I love the Ruby programming language, the Rails web development framework, and the RSpec testing library. These are well-designed tools with strong supporting ecosystems that allow me to work efficiently and to have fun doing it.

I have been a support engineer at CommonLit, a software engineer and support engineer at Hired (now part of LHH), a web development boot camp teaching assistant at App Academy, a high school math teacher, a public bus driver, and a long haul truck driver.

Skills

CloudflareA capable CDN and a vital layer of protection against DDoS attacks.
CSS3Because looking good is half the battle!
DockerA powerful tool for deploying web applications reliably and quickly. (This site is deployed using Docker Compose.)
Elasticsearch / OpenSearchA fast, powerful, and flexible search backend.
GitThe standard in version control.
GitHubWhere software teams and the open source community collaborate. GitHub Actions are great!
HerokuDoing (some of) the devops, so you don't have to.
HTML5The building block of the Internet!
JavaScriptA flexible language, essential for any modern web app. ES6 (plus lodash to fill in some utility functions) makes JavaScript coding pretty enjoyable.
JestA fast and effective JavaScript unit testing library.
JiraA quality tool for organizing software teams. I like Jira so much that I use it to plan and track work on my personal projects!
LodashLodash brings a lot of the conciseness, convenience, and clarity that I love about Ruby to the front end.
NodeJSNode and its package managers and frontend libraries are essential parts of the modern web stack.
PostgreSQLA fast, rock-solid, open source, and richly featured SQL database.
ReactDeclarative, reactive rendering and component-based development make React a superior alternative to direct DOM manipulation for client-side applications of more than trivial complexity.
RedisA fast, in-memory database.
RSpecI love testing, and RSpec makes tests readable and easy to write.
RubyRuby was designed for developer happiness, and it shows!
Ruby on RailsA web-development framework with a great ecosystem that makes development fast and fun. Rails's ActiveRecord ORM is superb.
SassIt's in the name - syntactically awesome style sheets. Why write CSS, when you can write Sass?
Tailwind CSSA utility-first CSS framework that makes styling quick and easy.
TypeScriptThe guarantees provided by types reduce the likelihood of bugs and enable tooling that can make the development process relatively efficient and even enjoyable compared to more dynamic languages.
VueJSA great framework for building front-end UX with a great supporting ecosystem. I hope that its popularity continues to grow.

Projects

DavidRunger.com

Rails 8, Vue 3

Welcome to davidrunger.com — my digital playground for experimenting with modern web technologies, where I host apps designed for everyday use by my family and me.

  • Emoji Picker - I couldn't find an emoji picker that met my needs (simple, fast, keyboard-first, and with the ability to customize emoji search keywords), so I built my own.
  • Groceries* - Simplify and streamline your family's grocery shopping with a collaborative, mobile-friendly, real-time (WebSockets-enabled) list.
  • Workouts* - An app for tracking workouts over time, and to stay on-pace within a workout.
  • Logs* - Track anything you like using various log types: text, number, duration, or counter.
  • Quizzes* - A multi-person quiz app that uses ActionCable websockets for real-time interactivity.
  • Check-ins* - Track how well your emotional needs are being met in your marriage/relationship.

*Google login required

Tech

  • A Rails 8 backend serves various Vue 3 front-end apps.
  • The app's deployment is managed with Docker Compose.
  • The app's 6,000+ lines of testable Ruby code are 100% covered by tests written with RSpec.
  • Vite Rails provides sub-second hot module replacement (HMR) in development, and compiles the application's TypeScript and CSS for production.
  • The primary database is PostgreSQL, plus Redis for Sidekiq, caching, and some direct use by the app.
  • Sidekiq processes background jobs.
  • NGINX exposes the server to the web.
  • Pinia provides client-side state management.
  • Google OAuth provides convenient and secure sign-in.
  • GitHub Actions provides continuous integration (CI) testing and linting and continuous deployment (CD).
  • Observability is provided by Grafana log search and metrics viewing, Prometheus metrics collection and storage, Loki log storage, Vector log transformation and routing, cAdvisor container monitoring, Node exporter system resource monitoring, and prometheus_exporter to provide Rails metrics for Prometheus.
  • Ruby code is linted by RuboCop, JavaScript by ESLint, and stylesheets by Stylelint. Brakeman checks for Rails security issues, and DatabaseConsistency and Immigrant help to ensure that the database is well-structured.
  • Tailwind provides CSS utility classes, so a lot of styling can be done within the markup itself.
  • JsRoutes allows the use of Rails named routes / path helpers on the client-side, too!
  • Element Plus provides aesthetic and ready-to-use Vue UI components.
  • A custom-built, pallets-based, parallelized test runner determines and executes the subset of tests and other checks that are needed for any given PR, making development and deployment as fast as possible, while ensuring application stability.
  • A custom-built, ferrum-based prerendering system captures and then serves a static HTML version of the JavaScript-based homepage, allowing me to enjoy the developer-friendly ergonomics of a Vue-based workflow in development, while still serving a simple HTML page in production for optimal rendering performance and search engine optimization (SEO).
  • Plus... Vue Router client-side routing, Flipper feature flags, Devise authentication, Active Admin admin backend, Draper decorators, Pundit authorization, alba model-to-JSON serialization, Action Mailer outbound emails, Action Mailbox inbound emails, Action Cable websockets, runger_actions form objects / command objects, Skedjewel Sidekiq job scheduling, PaperTrail model change tracking, Rack::Attack IP blocking and request throttling, Prosopite eager-loading enforcement, Gitleaks secret protection, AWS S3 blob storage, Rollbar error tracking, and Percy visual diff monitoring!

Vue Rails Model Explorer

Ruby, Rails, Vue 3
Serpent Game

When working on a feature that involves multiple different ActiveRecord models, keeping the relevant details about those models in one's head can be challenging, especially in an app one is not yet very familiar with. I built the Vue Rails Model Explorer so that I don't need to keep so much information in my head (or search through db/schema.rb and look at association declarations in app/models/). This interactive tool makes it fast and easy to explore the columns and associations of a Rails application's models.

The tool features keyboard navigation through associations from one model to another (arrow keys to select the association of interest and Enter or space to move to the target model), a quick selector to jump straight to any model (Ctrl-K on Linux, Cmd-K on macOS), and the ability to pin models (keyboard shortcut: "p") so that the columns of multiple related models can be viewed together.

SimpleCov::Formatter::Terminal

Ruby
SimpleCov::Formatter::Terminal

Having good test coverage is important to me. It lowers the chance of shipping bugs and makes it possible to update dependencies with confidence and without manual testing.

However, I couldn't find a way to get quick, detailed feedback about my app's code coverage while working on tests – so I wrote SimpleCov::Formatter::Terminal. It prints line-by-line code coverage information to the terminal after every test run, and includes info about branch coverage, as well, making it easy to see where test coverage is missing, and to add tests covering the uncovered code.

Thanks to dog-fooding SimpleCov::Formatter::Terminal on itself, I'm easily able to keep its code coverage at 100%.

Skedjewel

Crystal
skedjewel.yml

DavidRunger.com has some Sidekiq jobs that I want to run at various scheduled intervals. There are some great add-on gems that provide this functionality, like sidekiq-scheduler, but I wanted something that wasn't so dependent on Sidekiq internals.

Thus, partially as an excuse to try out the Crystal programming language, I wrote a simple job runner in Crystal called skedjewel, which I use to execute scheduled Sidekiq jobs for DavidRunger.com. I love the small memory consumption of the compiled skedjewel Crystal binary, since memory is a precious resource on my relatively small hobby server.

Assorted Gems

Ruby

Below are some of the Ruby gems that I've written.

  • runger_actions: The missing piece of Rails! Organize and validate the actions of your Rails application with this combined form object / command object.
  • shaped: Validate the shape of Ruby objects (hashes, arrays, and more). This is a dependency used in runger_actions (mentioned just above).
  • fcom: A CLI tool for parsing git history. I use this regularly.
  • living_document: Evaluate Ruby code live and inline in your editor while you edit a Ruby file, or a Markdown file that includes Ruby code snippets. LivingDocument is useful for quickly exploring ideas in Ruby code, since it can be faster and more convenient than working in IRB or running a Ruby script repeatedly as you edit it. It's also great for editing README.md documentation while ensuring the accuracy of example code snippets.
  • schedjewel: Execute Sidekiq jobs on a schedule. (This is essentially a Ruby version of the Crystal skedjewel project mentioned above.)