Defining methods

Ruby · Essentials · 12 min

Methods are the unit of reuse in Ruby, and keyword arguments are the idiomatic way to keep call sites readable.

Define a method with def name(params) ... end. The value of the last expression is returned automatically; return is only needed to exit early. Endless methods (Ruby 3.0) fit one-liners: def square(x) = x * x.

Parameter kinds, in the order they must appear:

  • Required positional: def greet(name).
  • Optional with a default: def greet(name, greeting = "Hello").
  • Splat *args collects extra positional arguments into an array.
  • Keyword arguments: def connect(host:, port: 5432). host: is required, port: optional. Callers write connect(host: "db", port: 6543), which is self-documenting and order-independent. Missing or unknown keywords raise ArgumentError.
  • Double splat **opts collects extra keywords into a hash.
  • A block parameter &block (covered with blocks).

Since Ruby 3.0, positional and keyword arguments are strictly separated: a hash passed positionally is no longer silently converted to keywords. Spread one explicitly with **hash.

Method names may end in ? (predicates), ! (dangerous or in-place) or = (setters). A method defined at the top level of a script becomes a private method on Object, callable anywhere in that script.

Methods can return multiple values as an array, which callers destructure: min, max = bounds(list).

Example

def greet(name, greeting = "Hello", punct: "!")
  "#{greeting}, #{name}#{punct}"
end

def connect(host:, port: 5432, **opts)
  "#{host}:#{port} #{opts}"
end

def bounds(list) = [list.min, list.max]

puts greet("Ada")                       # Hello, Ada!
puts greet("Bo", "Hi", punct: "?")      # Hi, Bo?
puts connect(host: "db", ssl: true)     # db:5432 {ssl: true}

settings = { host: "cache", port: 6379 }
puts connect(**settings)                # cache:6379 {}

low, high = bounds([4, 9, 1])
puts "#{low}..#{high}"                  # 1..9

begin
  connect(port: 1)
rescue ArgumentError => e
  puts e.message                        # missing keyword: :host
end

Remember

  • The last expression is the return value
  • Keyword arguments (name:) make calls self-documenting
  • Spread hashes into keywords explicitly with **

Watch out for

  • Passing a hash where keywords are expected without ** in Ruby 3, causing ArgumentError.

Check yourself

  1. Given def f(a, b: 2), what does f(1, b: 5) return if the body is a + b?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.ruby-lang.org/en/3.4/syntax/methods_rdoc.html