Part 4 · 1 chapters · ~8 min

Idioms

Idiomatic Ruby and Rails: small methods with clear names, Enumerable everywhere, guard clauses, duck typing, convention over configuration, RESTful resources, fat models but no god objects, service objects and concerns used sparingly, and the Rails doctrine.

5

Writing Ruby like Ruby

code
def withdraw(amount)
  return failure(:invalid_amount) unless amount.positive?        # guard clauses first
  return failure(:insufficient) if amount > available_kobo
  debit!(amount)
end

# RESTful resources, conventions do the wiring
resources :transfers, only: %i[index show create]                # → TransfersController#index/show/create

# a plain Ruby object for a multi-step operation (a "service object"), kept small
class Transfers::Create
  def self.call(...) = new(...).call
  def initialize(owner:, params:, idempotency_key:) = (@owner, @params, @key = owner, params, idempotency_key)
  def call
    Transfer.transaction do
      existing = Transfer.find_by(idempotency_key: @key) and return existing
      Transfer.create!(@params.merge(owner: @owner, idempotency_key: @key))
    end
  end
end
Rails doctrine (DHH)in practice
convention over configurationname things the Rails way and wiring disappears
the majestic monolithone well-organised app before services (Backend Architecture course)
exalt beautiful codereadable models and controllers over clever abstractions
provide sharp knivesmetaprogramming and callbacks are allowed; use them with judgement