Skip to content

Latest commit

 

History

6 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 

Repository files navigation

Coding guidelines

Read these rules on the web at claudiob.github.io/style — the live version lays them out three folders deep, and every rule there carries an Approve and a Reject button. Vote on the ones you keep and the ones you would throw out; the tallies below are those votes, counted.

Thirty rules, ten to a part. A rule lives in the widest part it is true in.

🧑‍💻 Principles · 💎 Ruby · 🛤️ Rails

Vote counts read from the live counters on 24 August 2026. For the current standing, visit the page.


🧑‍💻 Principles

What holds in any language.

Don’t store your customers’ phone, email, last name, street in plain text.


79% approve — 11 approve, 3 reject

Never write a method nobody calls. Never rescue an error nobody has incurred.


90% approve — 9 approve, 1 reject

Two calls on the same object in one expression are the tell: the second is unneeded.


45% approve — 5 approve, 6 reject

Between two versions carrying the same meaning, always pick the shorter name.


73% approve — 8 approve, 3 reject

claimed_by, matching — methods named like a query must not have any side effect.


100% approve — 9 approve, 0 reject

Every method that can be private must be private.


100% approve — 11 approve, 0 reject

Add a single-line comment above each class/constant/method that is not private.


60% approve — 6 approve, 4 reject

Small commits with long descriptions (why the code was shipped) and linear history.


90% approve — 9 approve, 1 reject

Full coverage and not one line more. Never test code you don’t own.


70% approve — 7 approve, 3 reject

Don’t Titleize. It’s ZIP not Zip. It’s license not licence. Respect the apostrophes.


90% approve — 9 approve, 1 reject


💎 Ruby

What holds in Ruby.

At most 100 lines in a file. At most 100 characters in a line. Comments count.


44% approve — 4 approve, 5 reject

You don’t need Service.new.call(params). Any method call is a code smell.


71% approve — 5 approve, 2 reject

Don’t interpolate method names at runtime. Don’t send. Don’t break the rules.


43% approve — 3 approve, 4 reject

Ruby does not care what class an object belongs to. Embrace the freedom. 🦆


83% approve — 5 approve, 1 reject

def foo(bar) opening with baz = bar.baz should have been foo(bar.baz).


100% approve — 5 approve, 0 reject

Taking **attributes only to hand them to a method makes params hard to follow.


83% approve — 5 approve, 1 reject

No need for attr_reader :foo if @foo can be used instead.


62% approve — 5 approve, 3 reject

A method can only return in its first line of code before any work starts.


50% approve — 3 approve, 3 reject

Omit on a call’s arguments; keep the inner ones where parsing needs them.


67% approve — 4 approve, 2 reject

Enhance RuboCop for code that is easy to grep and clean to diff:

  • Single quotes are the rule; double quotes only for interpolation and escape [1] [2]
  • Trailing comma on the last line of multiline literals (closing brace on its line) [3] [4]
  • when and else sit one level in from case and end [5]
  • private sits with class; private methods are indented like public ones[6]


80% approve — 4 approve, 1 reject


🛤️ Rails

What holds in Rails.

Extend with Concern, respect strong params, apply convention over configuration.

Embrace REST: endpoints are CRUD on resources. Add custom resources, never actions.


86% approve — 6 approve, 1 reject

Build off the main branch of rails/rails. Scrap any ~> from your Gemfile.

Order gems alphabetically and document inline why the app would break without them.


33% approve — 2 approve, 4 reject

Rails.cache wherever the same rows would be read or the same markup rendered.

Run tests with config.cache_store = :memory_store to verify caching works.


67% approve — 4 approve, 2 reject

Don’t pass instance variables to partials—use strict `` instead.


83% approve — 5 approve, 1 reject

Redirect out of the app with allow_other_host: true; after a non-GET with status: :see_other; break out of a frame with data: { turbo_frame: '_top' }.


50% approve — 3 approve, 3 reject

Eager-load associations. Check if records exist and loop over them in a single query.

Avoid the cost of User.all if all you display is User.select(:name, :email).


100% approve — 6 approve, 0 reject

Ensure every migration you write is reversible.

Use change before up/down. Use up_only before reversible { |dir| dir.up }.


100% approve — 6 approve, 0 reject

Clarify a decimal column price stores money with attribute :price, :amount.

All you need is to register a new type: Amount < ActiveRecord::Type::Decimal.


83% approve — 5 approve, 1 reject

Invoke encrypt on any sensitive data. Add deterministic: { fixed: false } to columns that must be queried or kept unique such as: User.find_by(email:).


83% approve — 5 approve, 1 reject

PostgreSQL offers native types and extensions that play well with Rails:

  • type: :citext to store case-insensitive strings such as emails
  • array: true to store an array in a single column
  • create_enum to declare enums backed by names, not integers


83% approve — 5 approve, 1 reject


Cast your own vote at claudiob.github.io/style.

About

Claudio’s manual of style

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors