Skills Development Idiomatic Ruby Coding Guidelines

Idiomatic Ruby Coding Guidelines

v20260617
ruby
A comprehensive reference guide detailing idiomatic and efficient coding practices in Ruby. It covers essential topics such as using Enumerable methods (map, select), modern string handling, robust error management, and proper module/class structuring. By adhering to these guidelines, developers can write cleaner, less verbose, and highly performant code that truly feels 'Ruby-like'.
Get Skill
198 downloads
Overview

Ruby: Idiomatic Efficiency Reference

Table of Contents

  1. Enumerable & Collections
  2. Blocks, Procs & Lambdas
  3. String Handling
  4. Error Handling
  5. Classes & Modules
  6. Ruby Idioms
  7. Anti-patterns specific to Ruby

1. Enumerable & Collections {#enumerable}

# ❌ Manual accumulation
result = []
items.each do |item|
  result << item.name.upcase if item.active?
end

# ✅
result = items.select(&:active?).map { |i| i.name.upcase }
# ❌ Manual grouping
grouped = {}
items.each do |item|
  grouped[item.category] ||= []
  grouped[item.category] << item
end

# ✅
grouped = items.group_by(&:category)
# ❌ Manual sum
total = 0
orders.each { |o| total += o.amount }

# ✅
total = orders.sum(&:amount)
# ❌ Checking existence then accessing
if hash.key?(key)
  value = hash[key]
end

# ✅
value = hash[key] # returns nil if missing
# or with default:
value = hash.fetch(key, default_value)
# or raising on missing:
value = hash.fetch(key) # raises KeyError

Prefer map/select/reject/sum over manual loops. Use &:method for single-method blocks.


2. Blocks, Procs & Lambdas {#blocks}

# ❌ Explicit block-to-proc conversion when unnecessary
items.map { |item| item.to_s }

# ✅
items.map(&:to_s)
# ❌ Proc.new when lambda is safer (arity check + return behavior)
handler = Proc.new { |x| x * 2 }

# ✅
handler = ->(x) { x * 2 }
# ❌ Multi-line block with { }
items.map { |item|
  result = transform(item)
  validate(result)
  result
}

# ✅ — do/end for multi-line, { } for single-line
items.map do |item|
  result = transform(item)
  validate(result)
  result
end

3. String Handling {#strings}

# ❌ String concatenation in loop
result = ""
items.each { |i| result += i.name + ", " }

# ✅
result = items.map(&:name).join(", ")
# ❌ String concatenation for assembly
greeting = "Hello, " + name + "! You have " + count.to_s + " messages."

# ✅
greeting = "Hello, #{name}! You have #{count} messages."
# ❌ Mutable string where frozen is fine (Ruby 3+ encourages frozen)
SEPARATOR = ", "

# ✅
SEPARATOR = ", ".freeze
# or add `# frozen_string_literal: true` at file top

Use heredocs (<<~HEREDOC) for multi-line strings. <<~ strips indentation.


4. Error Handling {#errors}

# ❌ Rescuing Exception (catches EVERYTHING including SignalException, SystemExit)
begin
  risky
rescue Exception => e
  log(e)
end

# ✅ — rescue StandardError (the default)
begin
  risky
rescue StandardError => e
  log(e)
  raise
end
# or just: rescue => e (same as StandardError)
# ❌ Using rescue as flow control
begin
  value = hash.fetch(key)
rescue KeyError
  value = default
end

# ✅
value = hash.fetch(key, default)
# ❌ Inline rescue hiding errors
result = dangerous_operation rescue nil

# ✅ — inline rescue only for truly trivial fallbacks
result = Integer(input) rescue nil  # acceptable for parsing

5. Classes & Modules {#classes}

# ❌ Manual accessors
class User
  def name
    @name
  end
  def name=(value)
    @name = value
  end
end

# ✅
class User
  attr_accessor :name
end
# ❌ Deep inheritance for shared behavior
class Animal; end
class Pet < Animal; end
class Dog < Pet; end

# ✅ — mixins for shared behavior, inheritance for "is-a"
module Trainable
  def train = puts("Training #{name}")
end

class Dog
  include Trainable
  attr_reader :name
  def initialize(name) = @name = name
end
# ❌ Class with only class methods (namespace via class)
class MathUtils
  def self.square(x) = x * x
  def self.cube(x) = x ** 3
end

# ✅
module MathUtils
  module_function
  def square(x) = x * x
  def cube(x) = x ** 3
end

6. Ruby Idioms {#idioms}

# ❌ Explicit boolean return
def active?
  if status == :active
    true
  else
    false
  end
end

# ✅
def active? = status == :active
# ❌ nil check before method call
if user && user.name
  puts user.name
end

# ✅ (Ruby 2.3+)
puts user&.name if user&.name
# or with safe navigation:
user&.name&.then { |n| puts n }
# ❌ Conditional assignment verbosely
if @cache.nil?
  @cache = expensive_compute
end

# ✅
@cache ||= expensive_compute
# ❌ Multiple assignment from array manually
first = arr[0]
second = arr[1]

# ✅
first, second = arr

7. Anti-patterns specific to Ruby {#antipatterns}

Anti-pattern Preferred
rescue Exception rescue StandardError
for x in collection collection.each
Manual attr_reader/writer attr_accessor / attr_reader
class for pure namespace module
String concatenation with + string interpolation #{}
if !condition unless condition
== true / == false truthy/falsy check directly
and/or for control flow &&/`
return at end of method implicit return (last expression)
Monkey-patching core classes in production refinements or wrapper
eval / send for known methods direct method call

Limitations

  • These are language-specific guidelines and do not cover overall architectural decisions.
  • Over-compression might reduce readability; apply judgement.
Info
Category Development
Name ruby
Version v20260617
Size 5.46KB
Updated At 2026-06-18
Language