Lesson 10 / 25
Method Arguments and Conventions
Use positional, optional, keyword and splat arguments, and follow naming conventions.
Flexible method signatures
Ruby methods accept required positional arguments, optional ones with defaults (def greet(name, greeting = "Hello")), a splat *args collecting extra positional arguments into an array, keyword arguments (def connect(host:, port: 443), where host: without a default is required), a double splat **opts collecting extra keywords into a hash, and a block parameter &block. Ruby 3 separates positional and keyword arguments strictly, so passing a hash where keywords are expected requires **hash. Use keyword arguments for anything optional or easily confused, such as booleans and units. Methods return the value of their last expression, and return is used mainly for early exits. Naming conventions carry meaning: ? for predicates returning booleans (empty?, valid?), ! for dangerous versions of a method that mutate or raise (save!, sort!), and = for setters (name=). Argument forwarding (...) passes all arguments through, handy in wrappers and decorators.
Kinds of method parameters
Positional, optional, splat, keyword, double splat and block parameters, in that order.
Keyword arguments, splats and forwarding
Readable calls and safe defaults.
def send_invoice(invoice, to:, cc: [], urgent: false, **headers)
subject = urgent ? "URGENT: #{invoice}" : invoice.to_s
puts "To #{to} (cc #{cc.join(', ')}): #{subject} #{headers}"
end
send_invoice("INV-7", to: "asha@example.com", urgent: true, reply_to: "billing@example.com")
def total(*amounts, discount: 0)
amounts.sum * (1 - discount)
end
puts total(100, 250, 50, discount: 0.1) # 360.0
options = { to: "ravi@example.com", cc: ["ops@example.com"] }
send_invoice("INV-8", **options) # pass a hash as keywords explicitly
def logged_send(...) # forward all arguments and the block
puts "sending..."
send_invoice(...)
end
logged_send("INV-9", to: "meera@example.com")Keywords for booleans
ship(order, true, false) is a puzzle. ship(order, express: true, gift_wrap: false) explains itself and cannot mix up the two flags.
Quick check: In `def connect(host:, port: 443)`, which statement is true?
- Both are optional
- host is positional
- host is a required keyword argument; port is optional with a default
- It is a syntax error
Answer
host is a required keyword argument; port is optional with a default — A keyword without a default value is required.