Ruby
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Methods and Blocks
-
Section 4: Object-Oriented Ruby
-
Section 5: Metaprogramming
-
Section 6: Working with Data and Files
-
Section 7: Ruby Frameworks Overview
-
Section 8: Ecosystem and Testing
-
Section 9: Practical Projects
-
Section 10: Interview Practice
-
Section 11: Data Structures and Algorithms in Ruby
-
Section 12: More Practice Exercises
-
Section 13: Enumerable and Functional Style
-
Section 14: More OOP Practice
-
Section 15: More Testing
-
Section 16: Enumerable and Comparable Modules In Depth
-
Section 17: Ruby Standard Library: Core Utilities
-
Section 18: Ruby Standard Library: Data and Security
-
Section 19: Ruby Standard Library: CLI and Text
-
Section 20: Ruby Networking
-
Section 21: Ruby on Rails Deep Dive
-
Section 22: Ruby Metaprogramming Deep Dive
-
Section 23: Ruby Design Patterns
-
Section 24: Ruby Concurrency
-
Section 25: Ruby Testing Deep Dive
-
Section 26: Ruby Gems and Packaging
-
Section 27: Ruby Performance
-
Section 28: More Practice Exercises
-
Section 29: More Interview Practice
-
Section 30: Rails API Development
-
Section 31: Rails Authentication and Authorization
-
Section 32: Rails Testing Deep Dive
-
Section 33: Rails Performance
-
Section 34: Rails Deployment
-
Section 35: Sinatra and Lightweight Ruby Web Apps
-
Section 36: More Ruby Language Deep Dive
-
Section 37: Ruby 3.x Modern Features
-
Section 38: More Data Structures in Ruby
-
Section 39: More Practical Projects
-
Section 40: Ruby Ecosystem Tools
-
Section 41: More Practice and Review
-
Section 42: Final Practice and Mastery
-
Section 43: Ruby Interview Deep Dive
-
Section 44: Ruby Background Processing Deep Dive
-
Section 45: Ruby GraphQL
-
Section 46: Ruby Object Model Deep Dive
-
Section 47: Ruby Hanami Framework Overview
-
Section 48: Ruby gRPC and Protocol Buffers
-
Section 49: Ruby Data Processing
-
Section 50: Ruby Search Integration
-
Section 51: Ruby File Upload and Media
-
Section 52: Ruby Email and Notifications
-
Section 53: Ruby Admin Panels
-
Section 54: Ruby Feature Flags and Experimentation
-
Section 55: Ruby Monitoring and Observability
-
Section 56: Ruby Docker and Deployment Deep Dive
-
Section 57: Ruby Security Deep Dive
-
Section 58: More Advanced Metaprogramming
-
Section 59: More Final Projects
9: Defining Methods
I've been working on a small prototype for a digital storefront, and I've hit a point where my code is starting to look like a messy grocery list. Every time I want to calculate a discounted price for an item, I'm writing the same bit of math over and over.
# This is getting tedious
item1_price = 100.0
item1_discount = 0.2
item1_final = item1_price * (1 - item1_discount)
item2_price = 50.0
item2_discount = 0.1
item2_final = item2_price * (1 - item2_discount)
puts item1_final
puts item2_final
Stopping the repetition
I can already tell that if I have fifty items, I'm going to lose my mind. I need a way to "package" this logic so I can just call it by name. In Ruby, that's where def comes in. I'll try to wrap that calculation into a method called apply_discount.
def apply_discount
price * (1 - discount)
end
puts apply_discount
If I run this, Ruby is going to scream at me. I get a NameError: undefined local variable or method 'price'. This is a great reminder that methods are like little isolated bubbles. The method apply_discount has no idea what item1_price is because that variable lives outside the method's scope. I can't just expect the method to "know" the data it's supposed to work on.
Passing data into the bubble
To fix this, I need to give the method a way to receive information. I'll add parameters—basically placeholders—inside the parentheses. Now, when I call the method, I'll pass the actual values into those placeholders.
def apply_discount(price, discount_rate)
price * (1 - discount_rate)
end
# Now I pass the specific values as arguments
puts apply_discount(100.0, 0.2)
puts apply_discount(50.0, 0.1)
That works. Now the method is reusable. It doesn't care if it's calculating a laptop or a bag of coffee; it just takes two numbers and does the math. I'm much happier with this.
The mystery of the return value
One thing that tripped me up when I first started with Ruby is how methods "give back" their results. I noticed that I didn't have to write a return keyword like you do in Java or JavaScript. I wondered, "Is it just returning nil by default?"
Let's test that by putting a puts inside the method instead of outside it:
def apply_discount(price, discount_rate)
result = price * (1 - discount_rate)
puts "Calculating... the total is #{result}"
result
end
final_price = apply_discount(100.0, 0.2)
puts "The variable final_price holds: #{final_price}"
When I run this, I see the "Calculating..." message, and then I see that final_price actually holds the number 80.0. Ruby has a very specific rule: the last expression evaluated in a method is automatically returned.
I could have written return result on the last line, and it would behave exactly the same. But in the Ruby community, we usually omit it unless we need to exit the method early (like inside an if statement). It keeps the code cleaner, which is something I've grown to really appreciate over the years.
📋 Practical Task
Building a Freelancer's Project Quote Calculator
Imagine you are building a tool to help a freelance developer generate quotes for clients. You need to create a method that calculates the total project cost based on an hourly rate, the estimated hours of work, and a flat "onboarding fee."
Your requirements:
- Define a method named
calculate_quote. - The method should accept three parameters:
hourly_rate,hours, andonboarding_fee. - The method should calculate the total by multiplying the rate by the hours and then adding the onboarding fee.
- Ensure the method returns the total value (do not just print it inside the method).
- Call the method with different sets of values and
putsthe results to the console to verify it works for multiple projects.
There are no comments for now.