🚀Advanced Ruby Methods and Modules: build a calculator in Ruby

Dumebi Okolo - Nov 6 '23 - - Dev Community

Hello

hello gif
In today's article, we will be looking at how to create and call methods or functions in Ruby with a solved example.
In this comprehensive guide, we will explore Ruby methods and modules with a solved example.

Table of Contents

 1. Modules in Ruby

       1.1. How to create modules in Ruby

             a. How to access a module in a Ruby file
 2. Blocks in Ruby
 3. Methods in Ruby

       3.2. Different types of methods in Ruby
 4. Practice example

       4.3. Build a simple calculator in Ruby

             b. Step 1

             c. Step 2

             d. Step 3
 5. Conclusion
 6. References

Modules in Ruby

I come from a JavaScript and React background. You can think of modules in Ruby as you'd think of components in React: independent and reusable bits of code. In the case of modules, they are stored in a separate file from the main file being used. In a module, you can store a method or function that can be called or used multiple times in your script.
It helps create a cleaner and easier-to-understand codebase.

How to create modules in Ruby

As earlier described, modules are stored in a separate file from the main code file.
In RubyMine by

, modules are differentiated from a normal ruby file by the presence of an 'M' symbol. Although ruby files and modules end with a file extension, with RubyMine it is visually possible to differentiate them.

Ruby modules

Modules are initialized by the keyword module followed by the capitalized name of the module and closed off by an end statement.



module ModuleA
end


Enter fullscreen mode Exit fullscreen mode

You can now go ahead to define your functions or message that you want to store in the module in between the module definition and the end statement.



module ModuleA
MESSAGE = 'This is a module!!!'
  def ModuleA.exponent(num1, num2)
    num1 ** num2
  end
end


Enter fullscreen mode Exit fullscreen mode

We will talk about methods and functions later in the article.

How to access a module in a Ruby file

There are various methods for accessing the contents of a module in a Ruby file.

  1. Using the require keyword: At the top of your Ruby file, you use the require with the relative path of module file to access it.
    require './modules/module_a'
    The extension is not required.

  2. Using the require require_relative keyword: At the top of your Ruby file, you use the require_relative with the module file name.
    require_relative 'module_a'

  3. Using the $LOAD_PATH global variable: At the top of your Ruby file, you use the $LOAD_PATH with the require keyword to specify the path the module file is located in.



$LOAD_PATH << '.' require 'module_a.rb'


Enter fullscreen mode Exit fullscreen mode

Blocks in Ruby

Certainly, I can expand the "Blocks in Ruby" section for you. Here's an extended version of that section:

Blocks in Ruby

In Ruby, blocks are powerful and versatile constructs that allow you to create anonymous pieces of code. They are akin to nameless functions or anonymous functions in other programming languages like JavaScript. Blocks don't have a name and can be easily passed as arguments to methods, making them a fundamental component of Ruby's syntax.

What is a Block?

A block in Ruby looks similar to a method, but it doesn't have a name. Instead, you pass it to a method as an argument, enclosed within a pair of curly braces {} or with the do...end keywords. Blocks can accept input from arguments and return a value, making them incredibly flexible.



# Using {} for a block
[1, 2, 3, 4, 5].each { |number| puts number * 2 }

# Using do...end for a block
[1, 2, 3, 4, 5].each do |number|
  puts number * 2
end


Enter fullscreen mode Exit fullscreen mode

In the example above, we use a block with the each method to iterate over an array of numbers and double each of them. The |number| is a parameter that represents each element of the array during iteration.

Common Uses of Blocks

Blocks are widely used in Ruby for various purposes, such as:

1. Iteration

Ruby's built-in methods often accept blocks for iterating through arrays, hashes, and other collections. It's a clean and concise way to perform an action on each element.



# Using a block for iteration
[1, 2, 3, 4, 5].each { |number| puts number * 2 }


Enter fullscreen mode Exit fullscreen mode

2. Custom Methods

You can define your methods that accept blocks as arguments. This allows you to create customizable behavior within your methods, enabling users to pass specific code to be executed.



def custom_method
  puts "This is the start of the method"
  yield if block_given?
  puts "This is the end of the method"
end

custom_method do
  puts "This code is inside the block"
end


Enter fullscreen mode Exit fullscreen mode

In this example, the custom_method accepts a block and executes it between the start and end messages.

3. Resource Management

Blocks can be used to manage resources efficiently. For instance, when working with files or database connections, blocks ensure that resources are properly opened and closed.



File.open("example.txt", "r") do |file|
  data = file.read
  # Perform operations with the file
end
# The file is automatically closed when the block ends


Enter fullscreen mode Exit fullscreen mode

Blocks and Procs

Blocks are closely related to Procs in Ruby. Procs are essentially blocks that can be assigned to variables and reused. They provide a way to encapsulate a block of code for future execution.



my_proc = Proc.new { |number| puts number * 2 }
[1, 2, 3, 4, 5].each(&my_proc)


Enter fullscreen mode Exit fullscreen mode

The & operator is used to convert a block into a Proc. Procs offer more flexibility as they can be passed around as objects, making them useful in various scenarios.

Methods in Ruby

Illustration of methods in Ruby

According to Wikipedia,

In computer programming, a function or subroutine is a sequence of program instructions that performs a specific task, packaged as a unit. This unit can then be used in programs wherever that particular task should be performed.

In other words, this means that a function or method in Ruby is a "container" of one or multiple lines of code aimed towards achieving a particular task or purpose.

Different types of methods in Ruby

Named Methods in Ruby

These types of Ruby methods or functions are initialized by the def keyword and closed with the end keyword.



def this_is_a_function
5+5
end

#to call the method
this_is_a_function

#output=> 10


Enter fullscreen mode Exit fullscreen mode

_To output or use named methods, we call it outside of the method scope. _

Methods with parameters in Ruby

These are just like the named Ruby Methods only that they have parameters. Parameters are enclosed within parentheses after the function name.
Ruby Methods can take parameters to enhance their functionality. Let's see an example of Ruby Methods with parameters.



def parameter_method(num1, num2)
num1 + num2
end

#method call
parameter_method(5, 6)

#output=> 11


Enter fullscreen mode Exit fullscreen mode

Parameters are like variables in that they store a value. These values are called arguments and given at the method call.

Methods with default parameters

In this type of Ruby method definition, values are assigned to the parameters by default to prevent running into an error when the method is called without including the arguments.



def parameter_method(num1 = 5, num2 = 5)
num1 + num2
end

#method call
parameter_method()

#output=> 11


Enter fullscreen mode Exit fullscreen mode

We see that in the method call above, we did not give values to the parameters because a default value was already assigned. We can run this code perfectly without incurring any errors. These default values can always been overridden at the method call by then assigning values to the parameters.

Keyword arguments

Say we have a Ruby method:



def greetings(salutation, name)
puts "#{salutation}, my name is #{name}."
end

#method call
greetings("Hello", "Dumebi")

#output=> "Hello, my name is Dumebi."



Enter fullscreen mode Exit fullscreen mode

Now, imagine a situation where the developer had to call this method much later down the codebase and had forgotten the order in which the parameters were placed; was it 'salutation', 'name' or the other way around. And for such a method as this, the order matters a lot for the statement to make sense.
In order to prevent this type of occurrence, Ruby has a way of fixing parameters to appear in the order they were written.



def greetings(salutaion:, name:)
puts "#{salutation}, my name is #{name}."
end

#method call
greetings(name: 'Dumebi', salutation: 'Hello')

#output=> "Hello, my name is Dumebi."


Enter fullscreen mode Exit fullscreen mode

We see in the example above that the order didn't matter, so long as gave each key a value pair. We can also give keyword parameters default arguments
parameter_method(salutation: 'Hello', name: 'Dumebi')

Lambda functions in Ruby

These are equivalent to anonymous functions in JavaScript. These are Ruby methods without a name and are denoted with the keyword lambda.



lambda {|x| puts x * 8}.call(8)


Enter fullscreen mode Exit fullscreen mode

Lambda methods are stored in blocks.
The .call() method is used to call lambda or anonymous functions.
Anonymous functions can be stored in a variable and are denoted with the arrow.



square = -> (x) { puts x * x}.call(8)


Enter fullscreen mode Exit fullscreen mode

Practice example in Ruby

In this solved example, we will be building a simple calculator with Ruby and incorporating all we have learned about Ruby Methods, and conditional statements in Ruby.

Build a simple calculator in Ruby

In this solution, we will be combining everything we have learned so far in Ruby and using methods.

Step 1

We will first define how the calculator works to our users.



puts 'This is an easy to use calculator'
puts 'a means add'
puts 's means subtract'
puts 'm means multiply'
puts 'd means division'
puts 'e means exponent'


Enter fullscreen mode Exit fullscreen mode

Step 2

We will go ahead and create a module and define our function or method in it.



module CalculatorModule
  MESSAGE = 'This is a calculator module'

  def CalculatorModule.calculator(first_number, second_number)
    print 'Input operator:'
    operator = gets.chomp
    result = case (operator)
             when 'a' then puts first_number + second_number
             when 's' then puts first_number - second_number
             when 'm' then puts first_number * second_number
             when 'd' then puts first_number / second_number
             when 'e' then puts first_number ** second_number
             else
               puts 'Not a valid operator'
             end
  end

end



Enter fullscreen mode Exit fullscreen mode

Step 3

Back in our main Ruby file, we go ahead and piece everything together.
Now, because we do not want our calculator method to run only once and want to give the user the chance to exit at will, we will incorporate that into our finishing by enclosing our code into a begin...end while block.



begin
  print 'Input first number: '
  first_number = gets.chomp.to_f
  print 'Input second number:'
  second_number = gets.chomp.to_f
  CalculatorModule.calculator first_number, second_number
  print 'do you want to continue? (y/n)'
  continue = gets.chomp
end while continue == 'y'


Enter fullscreen mode Exit fullscreen mode

The full file will look:



require_relative 'calculator_module'

puts 'This is an easy to use calculator'
puts 'a means add'
puts 's means subtract'
puts 'm means multiply'
puts 'd means division'
puts 'e means exponent'

begin
  print 'Input first number: '
  first_number = gets.chomp.to_f
  print 'Input second number:'
  second_number = gets.chomp.to_f
  CalculatorModule.calculator first_number, second_number
  print 'do you want to continue? (y/n)'
  continue = gets.chomp
end while continue == 'y'


Enter fullscreen mode Exit fullscreen mode

Calculators in Ruby

Certainly, here's a suitable conclusion for your article:

Conclusion

In this comprehensive guide, we've delved into the fascinating world of Ruby programming, exploring the core concepts of Ruby methods and modules. We've embarked on a journey that's taken us from understanding the role of modules in Ruby, creating them, and accessing their functionality, to unraveling the myriad types of methods at your disposal. Along the way, we've seen how blocks in Ruby provide a versatile means of crafting dynamic, anonymous pieces of code.

By the end of this adventure, you should now have a firm grasp of these essential components of the Ruby language. Here are some key takeaways:

  • Modules in Ruby: Think of modules as independent, reusable building blocks of code, similar to components in React. They contribute to a cleaner and more maintainable codebase.

  • Ruby Methods: Methods are the workhorses of Ruby programming. They encapsulate one or more lines of code, serving specific tasks or functions in your applications. Whether you're defining named methods, working with parameters, or harnessing the power of keyword arguments, Ruby Methods offer a level of flexibility and reusability that streamlines your code.

  • Blocks in Ruby: Blocks are the unsung heroes of Ruby, offering a flexible way to pass and execute code within methods. They enable you to iterate through collections, define custom behavior, and manage resources seamlessly.

As you continue your Ruby programming journey, the knowledge you've gained here will serve as a solid foundation. Whether you're building web applications, scripts, or exploring the depths of Ruby's versatility, you now possess the tools to write more efficient and organized code.

Remember, mastery comes with practice. As you explore and apply these concepts, you'll uncover their full potential and discover innovative ways to tackle your projects. So, keep coding, keep learning, and keep pushing the boundaries of what you can achieve with Ruby.

We hope you found this guide informative and insightful. If you have any questions or would like to explore more about Ruby, feel free to reach out. We're here to support your journey into the world of Ruby programming.

Happy coding! 🚀🔵

References

Image: methods in Ruby
Cover Image

That's all for today's article.
Follow me on X(formerly twitter)
Let us connect on Linkedin.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .