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 configuration | name things the Rails way and wiring disappears |
| the majestic monolith | one well-organised app before services (Backend Architecture course) |
| exalt beautiful code | readable models and controllers over clever abstractions |
| provide sharp knives | metaprogramming and callbacks are allowed; use them with judgement |