Style, Idioms and Best Practices

54.1 Idiomatic Ruby

# ✅ Idiomatic                                     # ❌ Non-idiomatic
names.each { |n| puts n }                          # for n in names do puts n end
return unless valid?                               # if !valid? then return end
items.empty?                                       # items.length == 0
user&.name                                         # user && user.name
count ||= 0                                        # count = 0 if count.nil?
"Hello, #{name}"                                   # "Hello, " + name
%w[a b c]                                          # ["a", "b", "c"]
nums.map(&:to_s)                                   # nums.map { |n| n.to_s }
hash.fetch(:key)                                   # hash[:key] || raise(...)
File.open(path) { |f| f.read }  /  File.read(path) # f = File.open(path); ...; f.close
def admin? = role == :admin                        # def is_admin; return role == :admin; end
items.each_with_object({}) { |i, h| h[i.id] = i }  # h = {}; items.each { |i| h[i.id] = i }; h
raise ArgumentError, "msg"                         # raise ArgumentError.new("msg")

54.2 Best Practices Checklist

✅ Follow the Ruby Style Guide (rubystyle.guide). Enforce it with RuboCop or Standard.

✅ Two-space indentation, snake_case methods, CamelCase classes, ?/! naming conventions.

✅ Small methods and classes (single responsibility). Prefer composition and modules over deep inheritance.

✅ Use # frozen_string_literal: true. Use Data/freeze for value objects.

✅ Prefer fetch for required keys, keyword arguments for clarity, guard clauses for early exits.

✅ Rescue specific exceptions. Define custom error hierarchies.

✅ Write tests (Minitest/RSpec) and measure coverage. Use CI.

✅ Use Bundler and commit Gemfile.lock for apps. Keep dependencies updated and audited.

✅ Document public APIs (YARD). Add RBS/Sorbet types for larger codebases.

✅ Prefer public_send over send. Pair method_missing with respond_to_missing?.

❌ Avoid global variables, @@class_variables, and monkey patching core classes (use refinements).

❌ Don't rescue Exception. Don't use eval with external input.

❌ Don't use for loops or and/or for boolean logic (only for control flow).

❌ Avoid "clever" metaprogramming when plain code is clearer.

54.3 Design Principles in Ruby

SOLID, DRY, KISS, YAGNI, the Law of Demeter ("tell, don't ask").

Patterns in Ruby: Service Objects, Form Objects, Query Objects, Decorators/Presenters (SimpleDelegator), Value Objects (Data), Null Object, Observer (callbacks/ActiveSupport::Notifications), Strategy (duck-typed objects or lambdas), Builder (DSL blocks), Adapter, Command, Repository.

Recommended reading: *Practical Object-Oriented Design* (Sandi Metz), the *99 Bottles of OOP* book, *Refactoring: Ruby Edition*.