Methods

In other programming languages the term you might use for a Ruby method is function, procedure, or subroutine. In Ruby everything is a method — a named piece of code that does a job, optionally takes arguments, and optionally returns a value.

Method names are written in snake_case.

Ruby has two kinds of methods: class methods and instance methods. You will meet both in the Classes and Objects chapter. For now, treat every method as a standalone piece of code.

Defining a Method

Suppose we repeat the same three lines of code in a program (for whatever reason):

hello-worldx3a.rb
puts 'Hello World!'
puts 'Hello World!'
puts 'Hello World!'

We can bundle these three lines into a method called three_times:

hello-worldx3b.rb
def three_times
  puts 'Hello World!'
  puts 'Hello World!'
  puts 'Hello World!'
end

Let’s test this in irb with load './hello-worldx3b.rb', which reads the file and makes its definitions available:

$ irb
>> load './hello-worldx3b.rb'
=> true
>> three_times
Hello World!
Hello World!
Hello World!
=> nil
>> exit

Parameters

Methods become much more useful when you can pass values into them. Parameters turn a fixed method into a flexible one:

hello-worldx3c.rb
def three_times(value)
  puts value
  puts value
  puts value
end
$ irb
>> load './hello-worldx3c.rb'
=> true
>> three_times('Hello World!')
Hello World!
Hello World!
Hello World!
=> nil

The parentheses around the argument are optional:

>> three_times 'Hello World!'
Hello World!
Hello World!
Hello World!
=> nil

Ruby gurus will turn up their noses at "unnecessary" brackets in your programs and probably pepper you with comparisons to Java. There is one simple rule in the Ruby community: the fewer brackets, the cooler you are. ;-)

You won’t get a medal for using fewer brackets, though. Decide for yourself what makes you happy.

If you call a method without the required argument you get an ArgumentError:

>> three_times
ArgumentError: wrong number of arguments (given 0, expected 1)

Default Values

You can give a parameter a default, which lets callers skip it:

hello-worldx3d.rb
def three_times(value = 'blue')
  puts value
  puts value
  puts value
end
$ irb
>> load './hello-worldx3d.rb'
=> true
>> three_times('Example')
Example
Example
Example
=> nil
>> three_times
blue
blue
blue
=> nil
>> exit

return

puts is nice for printing but most methods exist to produce a value. The return keyword ships a value back to the caller:

circle-a.rb
def area_of_a_circle(radius)
  pi = 3.14
  area = pi * radius * radius
  return area
end
$ irb
>> load './circle-a.rb'
=> true
>> area_of_a_circle(10)
=> 314.0
>> exit

Ruby lets you skip return — a method automatically returns the value of its last expression:

circle-b.rb
def area_of_a_circle(radius)
  pi = 3.14
  area = pi * radius * radius
  area
end

You can go one step further and drop the temporary variable too:

circle-c.rb
def area_of_a_circle(radius)
  pi = 3.14
  pi * radius * radius
end

All three versions are equivalent. Use return when it makes a method easier to read — for an early exit, say. Otherwise the implicit-return form is more idiomatic.

Agentic Coding Tip: The /simplify Slash Command

You just saw three versions of the same method — verbose, idiomatic, and compact. That’s a very common situation: working code that is wordier than it needs to be. It happens to everyone, especially in the first week of a new language.

Claude Code ships a built-in /simplify slash command that performs exactly this transformation. Open a file, run /simplify, and Claude returns a simpler version of the code with the same behaviour, written in more idiomatic Ruby (implicit returns, one-liners where sensible, method calls chained when chaining reads naturally).

Where it helps most:

  • First Ruby drafts from someone coming from another language (JavaScript const/return, Python-style guards) that still look foreign to a Ruby reader.

  • A method that grew a temporary variable per step when the whole thing could be one expression.

  • Tests and scripts written by accretion over a session, where repeated setup could be a single helper.

Where it doesn’t:

  • Anything that depends on the exact names of variables or methods used by other files. /simplify optimises for terseness and is willing to rename a local whose name was quietly documenting intent.

  • Code where the explicit, verbose form is the teaching point — a textbook example, a step in a migration plan, or a helper you want a colleague to read twice.

Treat /simplify as a "one file, one diff" tool. Always look at the diff before accepting; short code is not automatically better code.