Skip
Arish's avatar

12. Methods in Ruby


Methods in Ruby

Methods are reusable blocks of code that perform specific tasks. Ruby methods are elegant and flexible, making your code clean and maintainable.

Defining Methods

ruby
1# Basic method
2def greet
3  puts "Hello, World!"
4end
5
6greet  # => Hello, World!
7
8# Method with parameters
9def greet(name)
10  puts "Hello, #{name}!"
11end
12
13greet("Alice")  # => Hello, Alice!
14
15# Method with default parameters
16def greet(name = "Guest")
17  puts "Hello, #{name}!"
18end
19
20greet          # => Hello, Guest!
21greet("Bob")   # => Hello, Bob!

Return Values

In Ruby, methods automatically return the last expression:

ruby
1# Implicit return
2def add(a, b)
3  a + b  # This is returned automatically
4end
5
6result = add(3, 5)  # => 8
7
8# Explicit return
9def divide(a, b)
10  return "Cannot divide by zero" if b == 0
11  a / b
12end
13
14divide(10, 2)   # => 5
15divide(10, 0)   # => "Cannot divide by zero"
16
17# Multiple return values
18def min_max(numbers)
19  [numbers.min, numbers.max]
20end
21
22min, max = min_max([3, 1, 4, 1, 5])
23# min => 1, max => 5

Method Arguments

Positional Arguments

ruby
1def create_user(name, email, age)
2  { name: name, email: email, age: age }
3end
4
5create_user("John", "john@example.com", 30)

Keyword Arguments

ruby
1# Required keyword arguments
2def create_user(name:, email:)
3  { name: name, email: email }
4end
5
6create_user(name: "John", email: "john@example.com")
7# Order doesn't matter:
8create_user(email: "john@example.com", name: "John")
9
10# Optional keyword arguments with defaults
11def create_user(name:, email:, role: "user", active: true)
12  { name: name, email: email, role: role, active: active }
13end
14
15create_user(name: "John", email: "john@example.com")
16# => { name: "John", email: "john@example.com", role: "user", active: true }

Splat Operators

ruby
1# *args - collect remaining positional arguments
2def sum(*numbers)
3  numbers.reduce(0, :+)
4end
5
6sum(1, 2, 3, 4, 5)  # => 15
7
8# **kwargs - collect remaining keyword arguments
9def log(message, **options)
10  puts "#{message} (#{options})"
11end
12
13log("Error occurred", level: :error, timestamp: Time.now)
14
15# Combining all types
16def method(required, optional = "default", *args, keyword:, **kwargs)
17  # required - must be provided
18  # optional - has a default value
19  # *args - array of extra positional args
20  # keyword: - required keyword argument
21  # **kwargs - hash of extra keyword args
22end

Method Naming Conventions

Ruby has conventions for method names that convey meaning:

ruby
1# Question mark (?) - returns boolean
2def active?
3  @status == "active"
4end
5
6user.active?  # => true or false
7
8# Bang (!) - modifies object in place or dangerous operation
9name = "hello"
10name.upcase   # => "HELLO" (returns new string)
11name          # => "hello" (original unchanged)
12
13name.upcase!  # => "HELLO" (modifies in place)
14name          # => "HELLO" (original changed)
15
16# Setter methods (=)
17class User
18  def name=(value)
19    @name = value.strip
20  end
21end
22
23user.name = "  John  "  # Calls name= method
24
25# Private methods often start with underscore (convention)
26def _internal_calculation
27  # ...
28end

Blocks, Procs, and Lambdas

Blocks

Blocks are chunks of code passed to methods:

ruby
1# Block with do...end (multi-line)
2[1, 2, 3].each do |number|
3  puts number * 2
4end
5
6# Block with braces (single line)
7[1, 2, 3].each { |number| puts number * 2 }
8
9# Accepting a block in your method
10def with_timing
11  start = Time.now
12  yield  # Execute the block
13  puts "Took #{Time.now - start} seconds"
14end
15
16with_timing do
17  sleep(1)
18  puts "Working..."
19end
20
21# Block with arguments
22def repeat(times)
23  times.times { |i| yield(i) }
24end
25
26repeat(3) { |i| puts "Iteration #{i}" }

Procs

Procs are saved blocks you can reuse:

ruby
1# Creating a proc
2double = Proc.new { |n| n * 2 }
3# Or using proc
4double = proc { |n| n * 2 }
5
6double.call(5)    # => 10
7double.(5)        # => 10 (shorthand)
8double[5]         # => 10 (shorthand)
9
10# Using procs with methods
11[1, 2, 3].map(&double)  # => [2, 4, 6]
12
13# Converting methods to procs
14def triple(n)
15  n * 3
16end
17
18[1, 2, 3].map(&method(:triple))  # => [3, 6, 9]

Lambdas

Lambdas are like procs but stricter:

ruby
1# Creating a lambda
2multiply = ->(a, b) { a * b }
3# Or
4multiply = lambda { |a, b| a * b }
5
6multiply.call(3, 4)  # => 12
7
8# Differences from procs:
9# 1. Lambdas check argument count
10lam = ->(a, b) { a + b }
11lam.call(1)  # ArgumentError: wrong number of arguments
12
13# 2. return in lambda returns from lambda only
14def test_lambda
15  lam = -> { return "from lambda" }
16  lam.call
17  "from method"
18end
19test_lambda  # => "from method"
20
21def test_proc
22  p = proc { return "from proc" }
23  p.call
24  "from method"  # Never reached
25end
26test_proc  # => "from proc"

Method Visibility

ruby
1class User
2  # Public by default
3  def greet
4    puts "Hello!"
5  end
6
7  private
8
9  # Private methods - can only be called within the class
10  def secret_method
11    puts "This is private"
12  end
13
14  protected
15
16  # Protected - can be called by same class or subclasses
17  def internal_method
18    puts "This is protected"
19  end
20end
21
22user = User.new
23user.greet          # Works
24user.secret_method  # NoMethodError: private method called

Alias Methods

ruby
1class User
2  def full_name
3    "#{first_name} #{last_name}"
4  end
5  
6  alias_method :name, :full_name
7end
8
9user.full_name  # => "John Doe"
10user.name       # => "John Doe" (same method)

Method Missing

Handle calls to undefined methods:

ruby
1class FlexibleObject
2  def method_missing(method_name, *args)
3    puts "You called: #{method_name} with #{args}"
4  end
5end
6
7obj = FlexibleObject.new
8obj.anything("hello", 123)
9# => You called: anything with ["hello", 123]

Methods are the building blocks of Ruby programs. Understanding them deeply will help you write elegant Rails code!