Ruby Logo

Ruby Methods

Learn to define and use methods in Ruby with parameters, defaults, and best practices.

Home Ruby Ruby Methods

Ruby Methods Mastery

Methods are the building blocks of Ruby programming. They encapsulate behavior, promote code reuse, and enable clean, maintainable code. Ruby methods are flexible, powerful, and designed with programmer happiness in mind.

Built-in vs User-defined Methods

Built-in Methods: Ruby comes with thousands of pre-defined methods. User-defined Methods: Methods you create yourself using the def keyword.

Built-in Methods

# String methods
"hello".upcase
# "HELLO"
"hello".length
# 5
"hello".reverse
# "olleh"

# Array methods
[1, 2, 3].push(4)
# [1, 2, 3, 4]
[1, 2, 3].include?(2)
# true
[1, 2, 3].map { |x| x * 2 }
# [2, 4, 6]

# Numeric methods
5.odd?
# true
4.even?
# true
3.14.round
# 3
  • Available on all objects of that class
  • Part of Ruby's core library
  • Well-tested and optimized
  • Follow Ruby naming conventions

User-defined Methods

# Custom methods you create
def
greet(name)
"Hello, \#{name}!"
end

def
calculate_tax(amount)
amount * 0.08
end

def
is_adult?(age)
age >= 18
end
  • Created with def keyword
  • Customize behavior for your needs
  • Promote code reuse and organization
  • Can be defined in classes or globally

Method Calling & Usage Patterns

Method Calling: Ruby offers multiple ways to call methods, each with specific use cases and syntax variations.

Different Ways to Call Methods

# 1. Dot notation (most common)
"hello".upcase
# "HELLO"
[1, 2, 3].push(4)
# [1, 2, 3, 4]
Math.sqrt(16)
# 4.0

# 2. Parentheses (explicit)
"hello".upcase()
# "HELLO"
greet("Alice")
# "Hello, Alice!"

# 3. Send method (dynamic calling)
"hello".send(:upcase)
# "HELLO"
"hello".send("upcase")
# "HELLO"
method_name = "upcase"
"hello".send(method_name)
# "HELLO"

# 4. Public send (safer than send)
"hello".public_send(:upcase)
# "HELLO"

# 5. Method objects
upcase_method = "hello".method(:upcase)
upcase_method.call
# "HELLO"
upcase_method.()
# "HELLO" (shorthand)

Method Chaining

# Chain methods together
" hello world "
.strip
# "hello world"
.upcase
# "HELLO WORLD"
.split
# ["HELLO", "WORLD"]
.join("-")
# "HELLO-WORLD"

# One line chaining
result = " hello world ".strip.upcase.split.join("-")
puts
result
# "HELLO-WORLD"

# Array method chaining
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
result = numbers
.select { |n| n.even? }
# [2, 4, 6, 8, 10]
.map { |n| n * 2 }
# [4, 8, 12, 16, 20]
.reduce(0, :+)
# 60

Safe Method Calling

# Safe navigation operator (&.)
user = nil
user&.name
# nil (no error)
user&.name&.upcase
# nil (no error)

user = { name: "Alice" }
user&.name
# "Alice"
user&.name&.upcase
# "ALICE"

# Try method (returns nil if method doesn't exist)
"hello".try(:upcase)
# "HELLO"
"hello".try(:nonexistent)
# nil

# Respond to method check
"hello".respond_to?(:upcase)
# true
"hello".respond_to?(:nonexistent)
# false

if "hello".respond_to?(:upcase)
"hello".upcase
end

Method Definition Basics

Method Definition: Ruby methods are defined with the def keyword and end with end. They can accept parameters, perform operations, and return values automatically.

Basic Method Definition

# Simple method definition
def greet
"Hello, World!"
end

# Method with parameters
def greet_person(name)
"Hello, #{name}!"
end

# Method with multiple parameters
def calculate_area(length, width)
length * width
end

# Method with default parameters
def greet_with_style(name, style = "Hello")
"#{style}, #{name}!"
end

# Calling methods
puts greet # "Hello, World!"
puts greet_person("Alice") # "Hello, Alice!"
puts calculate_area(10, 5) # 50
puts greet_with_style("Bob") # "Hello, Bob!"
puts greet_with_style("Charlie", "Hi") # "Hi, Charlie!"

Method Naming Conventions

# Ruby method naming conventions
def calculate_total # snake_case for multi-word methods
def is_valid? # ? for boolean methods
def update! # ! for methods that modify the object
def to_s # to_* for conversion methods
def each # simple names for common operations
end

Ruby Convention: Ruby methods return the last evaluated expression automatically. No explicit return needed unless you want early returns!

Method Parameters

Ruby methods support various parameter types: required, optional (default), splat (*), keyword, and block parameters.

# Required parameters
def divide(a, b)
a / b
end
# Optional parameters (default values)
def greet(name, greeting = "Hello")
"#{greeting}, #{name}!"
end
# Splat parameters (*args) - accepts variable number of arguments
def sum(*numbers)
numbers.reduce(0, :+)
end
# Keyword arguments
def create_user(name:, email:, age: 18)
{
name: name,
email: email,
age: age
}
end
# Usage examples
puts greet("Alice") # "Hello, Alice!"
puts greet("Bob", "Hi") # "Hi, Bob!"
puts sum(1, 2, 3, 4, 5) # 15
user = create_user(name: "Alice", email: "alice@example.com")

Return Values & Early Returns

Ruby methods return the last evaluated expression, but you can use explicit return for early exits and clarity.

# Implicit return (Ruby style)
def square(n)
n * n # This value is automatically returned
end
# Explicit return
def divide_safely(a, b)
return "Cannot divide by zero" if b == 0
a / b
end
# Multiple return values
def min_max(array)
[array.min, array.max] # Returns an array
end
# Guard clauses pattern
def process_user(user)
return unless user
return unless user.valid?
return unless user.active?
# Main processing logic here
user.process!
end
# Using multiple returns
min, max = min_max([3, 1, 4, 1, 5])
puts "Min: #{min}, Max: #{max}" # "Min: 1, Max: 5"

Method Visibility

Ruby provides three levels of method visibility: public, private, and protected.

# Method visibility example
class BankAccount
def initialize(balance)
@balance = balance
end
# Public methods (default)
def deposit(amount)
return false if amount <= 0
@balance += amount
log_transaction("deposit", amount)
true
end
def balance
format_currency(@balance)
end
private # Everything below is private
def log_transaction(type, amount)
puts "#{Time.now}: #{type} of #{format_currency(amount)}"
end
def format_currency(amount)
"$#{'%.2f' % amount}"
end
protected # Can be called by other instances of same class
def transfer_to(other_account, amount)
return false if @balance < amount
@balance -= amount
other_account.receive_transfer(amount)
end
def receive_transfer(amount)
@balance += amount
end
end

Class vs Instance Methods

# Class and instance methods
class Calculator
# Class method - called on the class itself
def self.pi
3.14159
end
# Alternative class method syntax
class << self
def add(a, b)
a + b
end
def multiply(a, b)
a * b
end
end
# Instance method - called on instances
def initialize
@history = []
end
def calculate(operation, a, b)
result = case operation
when :add then a + b
when :subtract then a - b
when :multiply then a * b
when :divide then a / b
end
@history << "#{a} #{operation} #{b} = #{result}"
result
end
def history
@history
end
end
# Usage
puts Calculator.pi # 3.14159 (class method)
puts Calculator.add(5, 3) # 8 (class method)
calc = Calculator.new
puts calc.calculate(:multiply, 4, 7) # 28 (instance method)
puts calc.history # Shows calculation history

Method Chaining

Design methods to return self to enable fluent interfaces and method chaining.

# Chainable methods
class QueryBuilder
def initialize
@conditions = []
@order = nil
@limit_value = nil
end
def where(condition)
@conditions << condition
self # Return self for chaining
end
def order_by(column)
@order = column
self
end
def limit(count)
@limit_value = count
self
end
def to_sql
sql = "SELECT * FROM users"
sql += " WHERE #{@conditions.join(' AND ')}" unless @conditions.empty?
sql += " ORDER BY #{@order}" if @order
sql += " LIMIT #{@limit_value}" if @limit_value
sql
end
end
# Method chaining in action
query = QueryBuilder.new
.where("age > 18")
.where("active = true")
.order_by("name")
.limit(10)
puts query.to_sql
# "SELECT * FROM users WHERE age > 18 AND active = true ORDER BY name LIMIT 10"

Advanced Method Features

# Methods that accept blocks
def measure_time
start_time = Time.now
result = yield if block_given?
end_time = Time.now
puts "Execution time: #{end_time - start_time} seconds"
result
end
# Variable number of arguments with keyword args
def flexible_method(*args, **kwargs, &block)
puts "Regular args: #{args.inspect}"
puts "Keyword args: #{kwargs.inspect}"
yield("Block called") if block_given?
end
# Method aliasing
class String
alias_method :old_reverse, :reverse
def reverse
puts "Reversing string..."
old_reverse
end
end
# Usage examples
result = measure_time do
sleep(1)
"Task completed"
end
flexible_method(1, 2, name: "Alice", age: 30) { |msg| puts msg }

Interactive Practice: Method Calling & Usage

Practice Time: Try these method calling patterns and experiment with different ways to invoke methods. Understanding these patterns will make you a more effective Ruby programmer.

Interactive Code Runner

Ruby Code Editor
Output will appear here when you run the code...

Example 1: Built-in Method Exploration

# Explore string methods
text = " Hello, Ruby World! "
puts
text.strip
# "Hello, Ruby World!"
puts
text.upcase
# " HELLO, RUBY WORLD! "
puts
text.length
# 22
puts
text.include?("Ruby")
# true

# Try different calling methods
puts text.send(:upcase)
# Using send
puts text.public_send(:downcase)
# Using public_send
upcase_method = text.method(:upcase)
puts
upcase_method.call
# Using method object

Example 2: Method Chaining Practice

# Practice method chaining
sentence = " the quick brown fox jumps over the lazy dog "
result = sentence
.strip
# Remove whitespace
.capitalize
# Capitalize first letter
.split
# Split into words
.select { |word| word.length > 3 }
# Filter long words
.join(" | ")
# Join with separator
puts
result

# Array method chaining
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
sum_of_squares = numbers
.select { |n| n.even? }
# [2, 4, 6, 8, 10]
.map { |n| n ** 2 }
# [4, 16, 36, 64, 100]
.reduce(0, :+)
# 220
puts
"Sum of squares of even numbers: \#{sum_of_squares}"

Example 3: Safe Method Calling

# Practice safe navigation
user = nil
puts
user&.name&.upcase
# nil (safe)

user = { name: "Alice", email: "alice@example.com" }
puts
user&.name&.upcase
# "ALICE"

# Check if methods exist before calling
text = "hello"
if
text.respond_to?(:upcase)
puts text.upcase
end

if
text.respond_to?(:nonexistent_method)
puts "Method exists"
else
puts "Method doesn't exist"
end

Example 4: Dynamic Method Calling

# Dynamic method calling based on user input
text = "hello world"
operations = ["upcase", "downcase", "reverse", "capitalize"]

operations.each do |operation|
if text.respond_to?(operation)
result = text.send(operation)
puts
"\#{operation}: \#{result}"
end
end

# Method objects for later use
upcase_method = text.method(:upcase)
downcase_method = text.method(:downcase)

puts
upcase_method.call
# "HELLO WORLD"
puts
downcase_method.call
# "hello world"

Method Best Practices

✅ Do This

  • Use descriptive method names
  • Keep methods small and focused
  • Use keyword arguments for clarity
  • Return meaningful values
  • Handle edge cases gracefully
  • Use guard clauses for early returns

❌ Avoid This

  • Long parameter lists (use objects/hashes)
  • Methods that do too many things
  • Unclear or abbreviated names
  • Side effects in query methods
  • Deep nesting in methods
  • Modifying method arguments

Ruby Methods Mastery Checklist

  • Built-in Methods: Understand and use Ruby's extensive built-in method library
  • User-defined Methods: Create custom methods with def/end and descriptive names
  • Method Calling: Master dot notation, parentheses, send, and method objects
  • Method Chaining: Chain methods together for fluent, readable code
  • Safe Calling: Use safe navigation (&.) and respond_to? for robust code
  • Parameters: Master required, optional, splat, and keyword arguments
  • Returns: Understand implicit returns and when to use explicit ones
  • Visibility: Know when to use public, private, and protected
  • Types: Distinguish between class and instance methods
  • Dynamic Calling: Use send and method objects for flexible method invocation
  • Blocks: Use yield and block_given? effectively
  • Design: Write small, focused, single-purpose methods

Next Steps: Practice method calling patterns, experiment with built-in methods, and create your own user-defined methods. Understanding the different ways to call methods will make you a more versatile Ruby programmer!

Quick Navigation

Related Topics

Video Tutorial

Watch and learn ruby methods

Pro Tip: After reading through the content above, watch this video to reinforce your understanding and see the concepts in action!