Comprehensive Guide to Method Arguments in Ruby

2
2433

In this guide we will examine method arguments in Ruby, including:

  • The argument syntax
  • Named arguments
  • Default argument values
  • Splat arguments
  • Keyword splat arguments
  • Optional arguments

What are method arguments?

Before we can get into the code examples let’s first walk through what method arguments are. Let’s begin with a real world example.

large

Imagine that you have a machine that makes baseball bats. The workflow for the bat making process would be:

  1. The raw wood is placed in the machine.
  2. From there the machine takes the wood, cuts and polishes it.
  3. Lastly it finishes off by outputting the finished baseball bats from the machine.

So let’s see how this analogy applies to methods in Ruby:

large

  • Method Arguments – the raw wood placed inside the machine are the method arguments. This is data that can be provided by a user, a database query, an API, etc. It is rare for a method to not have arguments since method arguments are what allows for dynamic behavior. Looking back at our example, would it be possible to produce the baseball bats if we didn’t first supply the machine with the raw materials? Of course not. In the same way methods need data in order to work with.
  • The Method – the machine itself represents the method. This is where the actual logic goes that will produce the desired behavior.
  • The returned values – lastly the finished bats are like the values that get returned by methods.

Syntax for Method Arguments in Ruby

Now that you have a good idea on how methods work, let’s walk through how we can pass arguments to them.

Method Argument Code Examples

I’m going to start with a very basic example that prints out a user’s full name. This is actually a code snippet I took from a real world code project.

def full_name(first_name, last_name)
  first_name + " " + last_name
end

puts full_name("Jordan", "Hudgens")

As you’ll see this prints out my full name.

method arguments in ruby

The syntax for how to pass arguments to a method is to simply list them off on the same line that you declare the method. From here you can treat the names that you supplied as arguments (in this case first_name and last_name) as variables in the method.

Now there is also an alternative syntax that we can use that’s quite popular among Ruby devs for passing arguments to methods. Here is a slightly updated version of the code example from before:

def full_name first_name, last_name
  first_name + " " + last_name
end

puts full_name "Jordan", "Hudgens"

Notice how all of the parenthesis have been taken away? There is some debate on which option is better. I personally prefer to write less code when I have the chance to, so I prefer the second syntax. However both options will work well.

Named Arguments

Next on the list of method arguments in Ruby is the ability to name our arguments. This can be helpful when you have method signatures with a number of arguments and you want the method calls to be explicit. Here is how you can use named arguments in Ruby:

def print_address city:, state:, zip:
  puts city
  puts state
  puts zip
end

print_address city: "Scottsdale", state: "AZ", zip: "85251"

If you run this code it will work properly.

method arguments in ruby

So why are named arguments helpful? I think the easiest way to answer that question is to update our code and remove the named components. That code would look like this:

def print_address city, state, zip
  puts city
  puts state
  puts zip
end

print_address "Scottsdale", "AZ", "85251"

If you run this code it will work exactly like before.

method arguments in ruby

However by removing the named arguments we’ve made our method more difficult to work with and more prone to bugs. When working with a method as simple at print_addressit’s easy to know what the parameters city, state, and zip represent and to provide them in that order. However what if we had a method that looked like this:

def sms_generator api_key, num, msg, locale
  # Magic SMS stuff...
end

In a case like this we would have to reference the method declaration several times to ensure we’re passing in the arguments properly. And what would happen if we tried to call this method with the code:

sms_generator "82u3ojerw", "hey there", 5555555555, 'US'

Nothing looks wrong with this code, right? Actually this code won’t work because we’ve accidentally swapped the order of the phone number and message. In a real application the method would try to send the SMS message to the string hey there, which wouldn’t work for obvious reasons.

However if we update this method to use named arguments, the order no longer matters:

def sms_generator api_key:, num:, msg:, locale:
  # Magic SMS stuff...
end

sms_generator api_key: "82u3ojerw", msg: "hey there", num: 5555555555, locale: 'US'

When you utilize named arguments you don’t have to worry about the order that you pass the arguments in, which is a nice convenience and will also help prevent bugs in your program.

Default Argument Values

We’ll finish up our discussion on Ruby method arguments by discussing default values. There are many times when you’ll want to supply default values for an argument and Ruby let’s you implement this functionality quite easily.

Let’s take the example of building a method that streams movies. We’ll need the user to tell the method which movie to watch, however we don’t want them to have to enter in the language for the movie unless it’s different than English. In cases like this we can use default values with this syntax:

def stream_movie title:, lang: 'English'
  puts title
  puts lang
end

stream_movie title: 'The Fountainhead'

As you can see this will work properly and prints out English as the language because we declared it as a default.

method arguments in ruby

And now if we want to watch a movie in Spanish we can optionally pass in the lang argument into the method call:

stream_movie title: 'The Fountainhead', lang: 'Spanish'

Traditional Splat Arguments

One of my favorite components on Ruby is how explicit many of its methods are, and splat may be one of my favorites. The splat argument allows developers to pass an array of values into a method. Imagine that we are building a program that manages a baseball team. If we had a roster method that printed out all of the player names it would be messy to try to pass all of the names into the method one by one.

For example this is what it would look like if we simply tried to pass three players into the method manually:

def roster player1, player2, player3
  puts player1
  puts player2
  puts player3
end

roster 'Altuve', 'Gattis', 'Springer'

Technically this code would work. However this is a trivial example, a baseball team keeps 40 players on their roster. I wouldn’t even be able to fit the method on a single page if I tried passing in all of the players one by one. Thankfully this is where Ruby’s splat tool comes into play.

We can refactor our code to look like this:

def roster *players
  puts players
end

roster 'Altuve', 'Gattis', 'Springer'

The syntax for using the splat operator is to put an asterisk in front of the argument name. From that point you can pass one or any number of values to the method and they’ll all be stored in the splat argument.

method arguments in ruby

Once inside the method you can treat the argument like an array (I know we haven’t covered arrays yet, for right now think about them as a collection of objects).

This is a powerful tool because there are plenty of times when you’re going to need to pass values to a method but you won’t always know the exact number of items. In cases like thissplat is very handy.

Keyword based splat arguments

In addition to regular splat arguments that are essentially flexible containers for arguments, Ruby also allows for keyword based splat arguments. You can think about this tool as a cross between splat and keyword arguments.

Extending our baseball roster method. Let’s imagine that we need to give it the ability to print out the full list of players and positions. By leveraging keyword based splatarguments we can accomplish this feature. The code for this feature is below:

def roster **players_with_positions
  players_with_positions.each do |player, position|
    puts "Player: #{player}"
    puts "Position: #{position}"
    puts "\n"
  end
end

data = {
  "Altuve": "2nd Base",
  "Alex Bregman": "3rd Base",
  "Evan Gattis": "Catcher",
  "George Springer": "OF"
}

roster data

Here we’re storing our players and positions in a Ruby hash data structure called data. We’ll cover hashes later on in the course. For right know just know that hashes let you store key/value based data.

method arguments in ruby

In our roster method we’re declaring that we’re using the keyword based splat operator by putting the double asterisk in front of the argument. Inside of the method we’re looping over the data and printing out the respective player and position values. Notice how we can place block arguments inside the pipes (player and position in this case) that we can call with each loop iteration.

This is a great technique to use if you’re working with dynamic data that has a specific key/value based kind of structure. This is common when using database queries.

Optional Arguments

Last on our list of method arguments is the ability to pass optional arguments to a method. There are a number of times when you want flexibility with what types of data you pass to methods and that’s where optional arguments can come in handy.

Let’s imagine that we’re creating an invoice method. Our implementation needs to be flexible because some customers provide different data than others. We can accommodate this type of behavior by using code like this:

def invoice options={}
  puts options[:company]
  puts options[:total]
  puts options[:something_else]
end

invoice company: "Google", total: 123, state: "AZ"

When we run this program you can see some interesting behavior. We’re using the options hash in our method declaration. The term options is not required, you could use any word, but using options is considered a standard term to use.

From this point we can syntax such as options[:company] to grab the parameters that we want to use. There is a clear mapping between the name we call inside the method to the named argument we pass when we call the method. Also of note (and warning) is that this type of tool can cause silent bugs in your program. Do you notice how I attempted to print out options[:something_else] and I also passed an additional argument of state: "AZ" into the program? However these items did not throw an error. This means you need to be careful when you use optional arguments because they won’t fail, they simply won’t do anything.

method arguments in ruby

Summary

I hope that this has been a helpful guide to method arguments in Ruby and that you can use this as a reference to your own programs.

Resources

This guide was taken from my Comprehensive Ruby Programming book along with my video course which can be taken here: Comprehensive Ruby Programming.

2 COMMENTS

  1. Hi Jordan,
    I thank you for this excellent tutorial. I have just noticed you have inverted two screen shots: the screen shot under the paragraph “Traditional Splat Arguments” should go with the paragraph called “Optional Arguments”, and the shot under the paragraph “Keyword based splat arguments” should go where the first shot was.
    If it is not a trade secret, could please tell me how you create your markdown for the code parts of this tutorial? Do you use a Ruby gem, or is it a customized CSS style?
    Cheers,
    Pierre Liard

    • Thanks for letting me know, I’ve updated the images!

      And the markdown actually came with the WordPress theme I’m using: Laread. For devCamp, which is a Ruby application, we use the redcarpet and coderay gems to get the same syntax highlighting feature.

LEAVE A REPLY

Please enter your comment!
Please enter your name here