Runnable Ruby from the RubyConf Africa talk The Reviewable Codebase: Architecture and Performance Gates in Ruby, by Victor Turuthi.
Slides: https://www.turuthi.xyz/talks/reviewable-codebase/
One directory per example, covering the four properties: gates, budgets, boundaries and blessed paths.
Everything here is plain Ruby. No Rails, no database, no ActiveSupport — the query-budget example ships a forty-line notification bus of its own so the pattern can be read without framework knowledge. Where a Rails application would differ, the file says so.
bundle install
bundle exec rspec # 44 examples
bundle exec rubocop # clean
02_verify/bin/verify . # the whole gate, one command
bin/verify is the interesting one:
+ rubocop clean
+ rspec: 44 examples, 0 failures
+ query budget: within budget
Neither the Brakeman nor the pending-migrations verifier appears,
because this repository is not a Rails application and has no
db/migrate — that is the pattern working, not a gap. Each verifier
decides for itself whether it applies.
Three of these do work you would otherwise write yourself:
| Tool | Job | Where it runs |
|---|---|---|
brakeman |
Rails security warnings — SQL injection, mass assignment, unsafe redirects | A verifier: 02_verify/lib/verify/brakeman.rb |
prosopite / bullet |
Detect N+1s while the suite runs, and name the line | The test suite: 04_query_budget/rails/prosopite.rb |
derailed_benchmarks |
Memory and boot time, per gem | On demand, when a boot budget fails |
The detectors and the budget do different jobs and belong together. A detector tells you where the N+1 is; the budget asserts a number, so it also catches the page that got expensive without repeating itself, and stops the count creeping back once it is fixed.
| Directory | Property | What it shows |
|---|---|---|
01_discount_calculator |
Gates | A green test with full line coverage that verifies almost nothing, and the mutation run that measures the gap |
02_verify |
Gates | The verifier pattern: self-selecting checks, short failure output, no skip flag |
03_pre_push_hook |
Gates | Lint the diff, not the repository; fix before complaining |
04_query_budget |
Budgets | Query count as an assertion, and the N+1 it catches |
05_allocations |
Budgets | Allocations instead of wall-clock, because a flaky gate gets disabled |
06_boundaries |
Boundaries | The same feature as a fat controller and as a service object |
07_scope_check |
Boundaries | Did the change stay where it said it would? |
08_types_gate |
Gates | A signature on the boundary, and the spec that fails when the class drifts from it |
09_boot_budget |
Budgets | Boot time, the Puma worker that will not come up, and the manifest that catches it |
Every figure on a slide comes from this repository.
Mutation coverage — 32.78%
01_discount_calculator/bin/mutant-shipped
61 mutations, 20 killed, 41 alive against the shipped test. The
recorded run is in 01_discount_calculator/mutant_output.txt,
including the mutation that replaces @order.customer.vip? with
true and survives.
The same subject scored against the hardened suite:
01_discount_calculator/bin/mutant-shipped hardened
59 killed, 2 alive, 96.72%.
Query budget — 412 queries
The unbatched report costs one query for the orders plus three per order, so the count is a function of the fixture:
04_query_budget/bin/demo # 25 orders -> 76
04_query_budget/bin/demo --orders 137 # 137 orders -> 412
Boot budget — 0.007s and two libraries
09_boot_budget/bin/boot-profile
Adding one line — require "csv" — takes that to 0.057s and ten
libraries. Recorded in 09_boot_budget/boot_output.txt.
Allocations — 308
A fifty-item order serialises in 308 allocations on Ruby 3.4, the same number on every run. The budget in the spec is 400.
The slides are published at https://www.turuthi.xyz/talks/reviewable-codebase/ — their source lives in a separate repository, since it carries the speaker notes.
Each numbered directory keeps its own lib/ and spec/, so a
directory can be copied out on its own and still make sense. The
shared spec/spec_helper.rb puts every lib/ on the load path, which
is what lets one rspec run cover all of them.