Ruby 2.7 Reference SAVE UKRAINE

Methods implement the functionality of your program. Here is a simple method definition:

A method definition consists of the def keyword, a method name, the body of the method, return value and the end keyword. When called the method will execute the body of the method. This method returns 2 .

This section only covers defining methods. See also the syntax documentation on calling methods .

Method Names

Method names may be one of the operators or must start a letter or a character with the eighth bit set. It may contain letters, numbers, an _ (underscore or low line) or a character with the eighth bit set. The convention is to use underscores to separate words in a multiword method name:

Ruby programs must be written in a US-ASCII-compatible character set such as UTF-8, ISO-8859-1 etc. In such character sets if the eighth bit is set it indicates an extended character. Ruby allows method names and other identifiers to contain such characters. Ruby programs cannot contain some characters like ASCII NUL ( \x00 ).

The following are examples of valid Ruby methods:

Typically method names are US-ASCII compatible since the keys to type them exist on all keyboards.

Method names may end with a ! (bang or exclamation mark), a ? (question mark), or = (equals sign).

The bang methods ( ! at the end of the method name) are called and executed just like any other method. However, by convention, a method with an exclamation point or bang is considered dangerous. In Ruby’s core library the dangerous method implies that when a method ends with a bang ( ! ), it indicates that unlike its non-bang equivalent, permanently modifies its receiver. Almost always, the Ruby core library will have a non-bang counterpart (method name which does NOT end with ! ) of every bang method (method name which does end with ! ) that does not modify the receiver. This convention is typically true for the Ruby core library but may or may not hold true for other Ruby libraries.

Methods that end with a question mark by convention return boolean, but they may not always return just true or false . Often, they will return an object to indicate a true value (or “truthy” value).

Methods that end with an equals sign indicate an assignment method.

These are method names for the various Ruby operators. Each of these operators accepts only one argument. Following the operator is the typical use or name of the operator. Creating an alternate meaning for the operator may lead to confusion as the user expects plus to add things, minus to subtract things, etc. Additionally, you cannot alter the precedence of the operators.

  • - : subtract
  • * : multiply
  • % : modulus division, String#%
  • & : AND
  • ^ : XOR (exclusive OR)
  • >> : right-shift
  • << : left-shift, append
  • != : not equal
  • === : case equality. See Object#===
  • =~ : pattern match. (Not just for regular expressions)
  • !~ : does not match
  • <=> : comparison aka spaceship operator. See Comparable
  • < : less-than
  • <= : less-than or equal
  • > : greater-than
  • >= : greater-than or equal

To define unary methods minus and plus, follow the operator with an @ as in +@ :

The @ is needed to differentiate unary minus and plus operators from binary minus and plus operators.

You can also follow tilde and not ( ! ) unary methods with @ , but it is not required as there are no binary tilde and not operators.

Unary methods accept zero arguments.

Additionally, methods for element reference and assignment may be defined: [] and []= respectively. Both can take one or more arguments, and element reference can take none.

Return Values

By default, a method returns the last expression that was evaluated in the body of the method. In the example above, the last (and only) expression evaluated was the simple sum 1 + 1 . The return keyword can be used to make it explicit that a method returns a value.

It can also be used to make a method return before the last expression is evaluated.

Note that for assignment methods the return value will be ignored when using the assignment syntax. Instead, the argument will be returned:

The actual return value will be returned when invoking the method directly:

The standard syntax to define a method:

adds the method to a class. You can define an instance method on a specific class with the class keyword:

A method may be defined on another object. You may define a “class method” (a method that is defined on the class, not an instance of the class) like this:

However, this is simply a special case of a greater syntactical power in Ruby, the ability to add methods to any object. Classes are objects, so adding class methods is simply adding methods to the Class object.

The syntax for adding a method to an object is as follows:

self is a keyword referring to the current object under consideration by the compiler, which might make the use of self in defining a class method above a little clearer. Indeed, the example of adding a hello method to the class String can be rewritten thus:

A method defined like this is called a “singleton method”. broaden will only exist on the string instance greeting . Other strings will not have broaden .

When Ruby encounters the def keyword, it doesn’t consider it an error if the method already exists: it simply redefines it. This is called overriding . Rather like extending core classes, this is a potentially dangerous ability, and should be used sparingly because it can cause unexpected results. For example, consider this irb session:

This will effectively sabotage any code which makes use of the method String#to_i to parse numbers from strings.

A method may accept arguments. The argument list follows the method name:

When called, the user of the add_one method must provide an argument. The argument is a local variable in the method body. The method will then add one to this argument and return the value. If given 1 this method will return 2 .

The parentheses around the arguments are optional:

Multiple arguments are separated by a comma:

When called, the arguments must be provided in the exact order. In other words, the arguments are positional.

Repeated argument names is syntax error. There is one exception: the special name _ to designate unused argument(s).

This is useful for redefining methods, when client code expects a particular calling convention.

Default Values

Arguments may have default values:

The default value does not need to appear first, but arguments with defaults must be grouped together. This is ok:

This will raise a SyntaxError:

Default argument values can refer to arguments that have already been evaluated as local variables, and argument values are always evaluated left to right. So this is allowed:

But this will raise a NameError (unless there is a method named b defined):

Array Decomposition

You can decompose (unpack or extract values from) an Array using extra parentheses in the arguments:

This prints:

If the argument has extra elements in the Array they will be ignored:

This has the same output as above.

You can use a * to collect the remaining arguments. This splits an Array into a first element and the rest:

The argument will be decomposed if it responds to #to_ary . You should only define #to_ary if you can use your object in place of an Array.

Use of the inner parentheses only uses one of the sent arguments. If the argument is not an Array it will be assigned to the first argument in the decomposition and the remaining arguments in the decomposition will be nil :

You can nest decomposition arbitrarily:

Array/Hash Argument

Prefixing an argument with * causes any remaining arguments to be converted to an Array:

The array argument must be the last positional argument, it must appear before any keyword arguments.

The array argument will capture a Hash as the last entry if a hash was sent by the caller after all positional arguments.

However, this only occurs if the method does not declare any keyword arguments.

Also, note that a bare * can be used to ignore arguments:

Keyword Arguments

Keyword arguments are similar to positional arguments with default values:

Arbitrary keyword arguments will be accepted with ** :

When calling a method with keyword arguments the arguments may appear in any order. If an unknown keyword argument is sent by the caller, and the method does not accept arbitrary keyword arguments, an ArgumentError is raised.

To require a specific keyword argument, do not include a default value for the keyword argument:

When mixing keyword arguments and positional arguments, all positional arguments must appear before any keyword arguments.

It is possible to define a keyword argument with name that is not acceptable for a variable name, like class or next (keywords). In this case, argument’s value can be obtained via Binding .

Also, note that ** can be used to ignore keyword arguments:

To mark a method as accepting keywords, but not actually accepting keywords, you can use the **nil :

Calling such a method with keywords or a non-empty keyword splat will result in an ArgumentError. This syntax is supported so that keywords can be added to the method later without affected backwards compatibility.

Keyword and Positional Argument Separation

Between Ruby 2.0 and 2.6, keyword and positional arguments were not separated, and a keyword argument could be used as a positional argument and vice-versa. In Ruby 3.0, keyword and positional arguments will be separated if the method definition includes keyword arguments. In Ruby 3.0, if the method definition does not include keyword arguments, keyword arguments provided when calling the method will continue to be treated as a final positional hash argument.

Currently, the keyword and positional arguments are not separated, but cases where behavior will change in Ruby 3.0 will result in a warning being emitted.

There are a few different types of keyword argument separation issues.

Conversion of Hash to Keywords

If a method is called with the hash, the hash could be treated as keywords:

This occurs even if the hash could be an optional positional argument or an element of a rest argument:

However, if the hash is needed for a mandatory positional argument, it would not be treated as keywords:

Conversion of Keywords to Positional Arguments

If a method is called with keywords, but it is missing one mandatory positional argument, the keywords are converted to a hash and the hash used as the mandatory positional argument:

This is also true for empty keyword splats:

Splitting of Positional Hashes or Keywords

If a method definition accepts specific keywords and not arbitrary keywords, keywords or a positional hash may be split if the hash includes both Symbol keys and non-Symbol keys and the keywords or positional hash are not needed as a mandatory positional argument. In this case, the non-Symbol keys are separated into a positional argument hash, and the Symbol keys are used as the keyword arguments:

Block Argument

The block argument is indicated by & and must come last:

Most frequently the block argument is used to pass a block to another method:

If you are only going to call the block and will not otherwise manipulate it or send it to another method using yield without an explicit block parameter is preferred. This method is equivalent to the first method in this section:

Exception Handling

Methods have an implied exception handling block so you do not need to use begin or end to handle exceptions. This:

May be written as:

Similarly, if you wish to always run code even if an exception is raised, you can use ensure without begin and end :

You can also combine rescue with ensure and/or else , without begin and end :

If you wish to rescue an exception for only part of your method, use begin and end . For more details see the page on exception handling .

Method definition as an expression

def (method definition) is an expression returning the name of the defined method. This feature is mostly useful for method decoration:

private and memoize above are just method calls, receiving the result of def (method name to make private/cached) as their argument.

The alias keyword is most frequently used to alias methods. When aliasing a method, you can use either its name or a symbol:

For methods, Module#alias_method can often be used instead of alias .

You can also use alias to alias global variables:

You may use alias in any scope.

The undef keyword prevents the current class from responding to calls to the named methods.

You may use symbols instead of method names:

You may undef multiple methods:

You may use undef in any scope. See also Module#undef_method

LaunchSchool: An online school for Software Engineers

  • Open Bookshelf Cover Page
  • No Offline Access?
  • Introduction
  • A Brief History of Ruby
  • Computer Science and Layers of Abstraction
  • Who This Book is For
  • How to Read This Book
  • Preparations
  • Installing Ruby
  • Using a Code Editor
  • Stylish Ruby
  • Reading Documentation
  • Using the Command Line and irb
  • What Are Ruby "Gems"?
  • Debugging Ruby Code with Pry
  • About the Exercises
  • Type Conversion
  • Basic Data Structures
  • Expressions and Return
  • puts vs return
  • What is a Variable?
  • Assigning Value to Variables
  • Getting Data from a User
  • Variable Scope
  • Types of Variables

What Are Methods and Why Do We Need Them?

Obj.method or method(obj), mutating arguments, puts vs return: the sequel, chaining methods, method calls as arguments, the call stack.

  • Flow Control
  • Conditionals
  • Comparisons
  • Combining Expressions
  • Ternary Operator
  • Case Statement
  • True and False
  • Loops & Iterators
  • A Simple Loop
  • Controlling Loop Execution
  • While Loops
  • Until Loops
  • Do/While Loops
  • Conditionals Within Loops
  • What is an Array?
  • Modifying Arrays
  • Iterating Over an Array
  • Methods With a !
  • Mutating the Caller and Arguments
  • Nested Arrays
  • Comparing Arrays
  • Common Array Methods
  • each vs map
  • What is a Hash?
  • Iterating Over Hashes
  • Hashes as Optional Parameters
  • Hashes vs. Arrays
  • A Note on Hash Keys
  • Common Hash Methods
  • A Note on Hash Order
  • Ruby Standard Classes
  • Variables as Pointers
  • Blocks and Procs
  • Exception Handling
  • Exceptions & Stack Traces
  • Method Definition Order
  • Conclusion & Next Steps
  • Congratulations
  • Object Oriented Programming

You'll often have a piece of code that needs to be executed many times in a program. Instead of writing that piece of code over and over, there's a feature in most programming languages called a procedure, which allows you to extract the common code to one place. In Ruby, we call it a method . Before we can use a method, we must first define it with the reserved word def . After the def we give our method a name. At the end of our method definition, we use the reserved word end to denote its completion. This is an example of a method definition named say :

There's a comment in the method body to show you where the logic for the method definition will go. Why do we want a method named say ? To say something, of course! Suppose we had the following code in a file named say.rb . Create this file and type these examples along.

Notice how we've duplicated the puts many times. We'd like to have one place where we can puts and send that one place the information we want to puts . Let's create a method definition to do that.

On first glance this may seem silly, since we didn't save any lines of code, and in fact added more code. But what we've done is extracted the logic of printing out text, so that our program can have more flexibility.

We call (or invoke) the method by typing its name and passing in arguments. You'll notice that there's a (words) after say in the method definition. This is what's called a parameter . Parameters are used when you have data outside of a method definition's scope, but you need access to it within the method definition. If the method definition does not need access to any outside data, you do not need to define any parameters.

You will also see the term method invocation to refer to calling a method.

You can name parameters whatever you'd like, but like we said earlier, it is always the goal of a good programmer to give things meaningful and explicit names. We name the parameter words because the say method expects some words to be passed in so it knows what to say! Arguments are pieces of information that are sent to a method invocation to be modified or used to return a specific result. We "pass" arguments to a method when we call it. Here, we are using an argument to pass the word, or string of words, that we want to use in the say method definition. When we pass those words into the method definition, they're assigned to the local variable words and we can use them however we please from within the method definition. Note that the words local variable is scoped at the method definition level; that is, you cannot reference this local variable outside of the say method definition.

When we call say("hello") , we pass in the string "hello" as the argument in place for the words parameter. Then the code within the method definition is executed with the words local variable evaluated to "hello".

One of the benefits that methods give us is the ability to make changes in one place that affect many places in our program. Suppose we wanted to add a . at the end of every string we send to the say method. We only have to make that change in one place.

Run this code using the ruby say.rb command from your terminal to see the result. We've now added a . on each line and we only had to add it once in our program. Now you're starting to see the power of methods.

Default Parameters

When you're defining methods you may want to structure your method definition so that it always works, whether given arguments or not. Let's restructure our say method definition again so that we can assign a default parameter in case the calling code doesn't send any arguments.

You'll notice that say() prints hello. to the console. We have provided a default parameter that is used whenever our method is called without any arguments. Nice!

Optional Parentheses

Many Rubyists will leave off parentheses when calling methods as a style choice. For example, say() could be rewritten as just say . With arguments, instead of say("hi") , it could just be say "hi" . This leads to more fluid reading of code, but sometimes it can be confusing. Keep that in mind when you're reading Ruby; it can get tricky deciphering between local variables and method names!

Method Definition and Local Variable Scope

Before moving on to the next topic on methods, let's take a moment to discuss the concept of local variable scope within a method definition. A method definition creates its own scope outside the regular flow of execution. This is why local variables within a method definition cannot be referenced from outside of the method definition. It's also the reason why local variables within a method definition cannot access data outside of the method definition (unless the data is passed in as an argument).

Let's practice this concept with the following example:

What's the value of a? Still 5, because method definitions create their own scope that's entirely outside of the execution flow.

Make sure you don't mix up method invocation with a block and method definition when you're working with local variable scope issues. They may look similar at first, but they are not the same. They have different behaviors when it comes to local variable scope.

There are two ways to call methods that we will discuss in this book. The some_method(obj) format is when you send arguments to a method call; in the previous example, obj is the argument being passed in to the some_method method. Sometimes, you will see methods called with an explicit caller , like this a_caller.some_method(obj) . For now it's best to think of the previous code as some_method modifying a_caller . You'll have to memorize which way is required to call a method for now.

Sometimes, when calling a method, one or more arguments can be altered permanently; that is, we are mutating arguments .

We (Launch School) sometimes refer to mutating an argument as mutating the caller . This is technically incorrect since mutating the caller refers to a similar but distinct concept. We're gradually correcting these misuses of the term, but you're probably going to see us misuse this term from time to time, especially in older material.

Before diving further into mutating arguments, recall that we previously stated that method parameters are scoped at the method definition level, and are not available outside of the method definition. For example:

In the above code, we passed in a to the some_method method. In some_method , the value of a is assigned to the local variable number , which is scoped at the method definition level. number is reassigned the value "7". Did this affect a 's value? The answer is no, because number is scoped at the method definition level and a 's value is unchanged. Therefore, we proved that method definitions cannot modify arguments passed in to them permanently.

One thing to keep in mind is that we can mutate objects. That's not the same thing as changing the variable, though it can be hard to see the difference. For instance, let's say we have a local variable a that stores an array. (We'll cover arrays in more depth later. For now, just think of arrays as ordered lists.) Type the following code into a file named mutate.rb and run it to see the result.

We use p instead of puts here. These two are very similar with only small differences to the way Ruby prints the output. You can try both to see why we chose to use p .

If you haven't seen the #pop method before, check out the documentation .

Notice the difference between each print out? We have permanently modified the array that local variable a references by passing it to the mutate method, even though a is outside the method definition's scope. This is because the pop method mutates its calling object (the array specified by array ). a is still pointing to the same array, but, in this case, the number of elements in the array has changed.

Let's contrast this with a method that does not mutate the argument but still returns the same value.

You'll notice that we have the same output before and after the method invocation, so we know that a was not modified in any way. This is because the last method does not mutate the calling object, array , on line 5, so the array passed to no_mutate is not mutated.

How do you know which methods mutate arguments and which ones don't? Unfortunately, you have to memorize it by looking at the documentation or through repetition.

If you have experience programming in other languages and are wondering if Ruby is a pass-by-value or pass-by-reference language, then you might be disappointed with the answer. In a way, Ruby is both! We'll discuss this later in the Core Curriculum.

Now that you know what a method is and how it works, we can discuss the difference between puts and return . You haven't really been properly introduced to return but that's because in Ruby, every method returns the evaluated result of the last line that is executed.

Let's use our mutate.rb file to demonstrate this.

We're using the p method to print out the value of whatever the mutate method returns. Our output looks like this:

Here's what's happening:

  • We print out a as we initially defined it.
  • We print out the value returned by the mutate method.
  • We print out the value of a after the mutate method.

The second line, where it's returning a "3", is probably confusing you a little bit. What's happening is that the method is returning the result of array.pop back to where it's being called from. pop is a method in the Array class that removes the last element of an array and returns it.

Before we wrap this up, let's look at return by itself so we can fully understand it. Let's create a file called return.rb to demonstrate. Remember to type these examples out and create the files, your fingers are learning without you knowing it! Let's go!

Here we're assigning the returned_value to the value returned by the add_three method. Then we print returned_value to the output to see what it has inside it. Your output should print 7 because that's what the method call returned.

Ruby methods ALWAYS return the evaluated result of the last line of the expression unless an explicit return comes before it.

If you wanted to explicitly return a value you can use the return keyword.

Your output should still be the same, right? What happens if we change this again? What will print to the screen, if we run the code below?

The program above should still output 7 , the number you told it to return.

When you place a return in the middle of the add_three method definition, it just returns the evaluated result of number + 3 , which is 7, without executing the next line.

One of the major points that you will want to take away from this section is that the return reserved word is not required in order to return something from a method. This is a feature of the Ruby language. For example, consider this method definition:

The value of just_assignment(2) is going to be 5 because the assignment expression evaluates to 5, therefore that's what's returned.

That about covers methods. You are getting wiser and more confident with Ruby. We have a good feeling that you're probably starting to have a good time as well. Keep going! It only gets better from here.

Because we know for certain that every method call returns something, we can chain methods together, which gives us the ability to write extremely expressive and succinct code.

Suppose we create the following method definition:

The above method will return - not print out, but return - the value passed in incremented by 3. We can use it like this:

Since the add_three method call returns a value, we can then keep calling methods on the returned value.

This means that we're calling the times method on the returned value of add_three(5) , which is 8. Run the above in irb and you get:

Note the last line. That means the entire expression add_three(5).times { puts 'this should print 8 times'} returned 8, which implies we can keep chaining method calls if we wanted to!

In Ruby, it's common to see methods being chained together to form elegant code. For example:

This is because the String length method returns an integer, and we can call to_s on integers to convert them into strings.

Ok, back to our original add_three method definition. Let's make a small modification:

Notice that we're now using puts to output the incremented value, as opposed to implicitly returning it. Will the code below work?

If we run the code, we get this error:

It looks like somewhere along the line, we got a nil and nil does not know how to respond to a times method call. Let's take things step by step and just run add_three(5) . You should see something like this:

Notice that it prints the incremented value as expected, but the return value is nil . It turns out that puts always returns nil . Since puts n + 3 is the last expression in the method definition, add_three returns nil . We can now no longer use add_three to keep chaining methods since it returns nil .

This is a very important aspect of chaining methods together: if anywhere along the chain, there's a nil return value or an exception is thrown, the entire chained call will break down. If we want the add_three method to print the incremented value as well as return it, we have to make this fix:

We could use return new_value as well, but since new_value is the last expression in the method definition, it's being implicitly returned.

Thus far, we've become familiar with how methods are called. Let's take some simple examples to go over this concept. We're going to define add and subtract methods and call them:

We've defined two methods add and subtract that take parameters a and b . We assume both are integer values. Recall that Ruby implicitly returns the last line of a method; since both method definitions here contain just one line each, we're letting Ruby do its magic by using implicit return. Note that we could have also used explicit return to be more specific.

Now let's call these methods by passing integer values:

What is less obvious is that Ruby actually allows us to pass a method call as an argument to other methods. Stated differently, we're saying we can pass add(20, 45) and subtract(80, 10) as arguments to another method.

Remember that these method calls return integer values which is what allows us to perform such an operation. In other words, the returned value is what is being passed as arguments. We'll illustrate by defining a multiply method:

Now, let's pass add(20, 45) and subtract(80, 10) as arguments to multiply :

Let's see a more complicated example:

Let's break down what this is doing:

  • First, we're passing add two arguments: subtract(80, 10) and multiply(subtract(20, 6), add(30, 5)) .
  • The first argument, the subtract method call, returns 70 .
  • Here, subtract(20, 6) returns 14 and add(30, 5) returns 35 thus the method call becomes multiply(14, 35) . Evaluating multiply(14, 35) now returns 490 .
  • Finally, putting together the return values of those two method calls, we have add(70, 490) which ultimately returns 560 .

One very important thing to be aware of when using nested method calls is the use of parentheses to prevent any kind of confusion.

We've seen that method calls always return a value and we can pass that method call as an argument to another method call based on the returned value. Thus it's vital to know what our defined methods are returning, since in the final analysis, this is what is actually being passed as arguments to other method calls.

One important aspect of methods that all programmers need to understand is the concept of the call stack , or more casually, the stack .

The call stack helps Ruby keep track of what method is executing as well as where execution should resume when it returns. To do that, it works like a stack of books: if you have a stack of books, you can put a new book on the top or remove the topmost book from the stack. In much the same way, the call stack puts information about the current method on the top of the stack, then removes that information when the method returns.

In Ruby, methods aren't the only thing that uses the call stack. Blocks, procs, and lambdas also use the call stack; in fact, they all use the same call stack as Ruby uses for methods. For simplicity, we will usually just mention methods when discussing the call stack. However, you should always remember that blocks, procs, and lambdas are also part of this process.

Let's assume that we have the following code:

When this program starts running, the call stack initially has one item -- called a stack frame -- that represents the global (top-level) portion of the program. The initial stack frame is sometimes called the main method. Ruby uses this frame to keep track of what part of the main program it is currently working on.

Call Stack
-
-
-
main

When program execution reaches the method invocation on line 10, it first updates the main stack frame with the current program location. Ruby will use this location later to determine where execution should resume when second finishes running.

After setting the location in the current stack frame, Ruby creates a new stack frame for the second method and places it on the top of the call stack: we say that the new frame is pushed onto the stack. Our call stack now looks like this:

Call Stack
-
-
second
main: line 10

Note that the frame for the second method is now stacked on top of the main frame. While the second frame is still on the stack, main remains stuck beneath it, inaccessible. At the same time, the main method becomes dormant and the second method becomes active.

The second method calls the first method on line 6. That action causes Ruby to update the second frame so that Ruby will know where to resume execution later. It then creates a new stack frame for the first method and pushes it to the call stack.

Call Stack
-
first
second: line 6
main: line 10

Once the first method begins executing, it invokes the puts method. All Ruby methods, including the built-in ones like puts , share the same call stack. Therefore, we need to record our current location and then push a new frame to the stack:

Call Stack
puts
first: line 2
second: line 6
main: line 10

Chances are, puts also has several internal method calls. However, we will ignore them and just assume that puts does all its work without any additional method calls. Instead, it just logs the message first method to the console, then immediately returns.

When puts returns, Ruby removes -- pops -- the top frame from the call stack. That's the frame for puts in this example. That leaves the previous stack frame exposed. Ruby uses this frame to determine where execution should resume. In this case, execution resumes immediately after line 2.

Call Stack
-
first: line 2
second: line 6
main: line 10

Eventually, the first method will return. When that happens, the first frame gets popped from the stack. That exposes the stack frame for second , and that, in turn, tells Ruby that it should resume execution on line 6.

Call Stack
-
-
second: line 6
main: line 10

Next, execution jumps to the puts call on line 7. Like before, the current location is recorded and a new frame is pushed to the stack:

Call Stack
-
puts
second: line 7
main: line 10

When this puts call returns, the stack frame gets popped and execution returns to second .

Call Stack
-
-
second: line 7
main: line 10

When second finishes executing, the stack frame for second gets popped from the call stack, exposing the stack frame for main . The main frame tells Ruby to resume execution on line 10.

Call Stack
-
-
-
main: line 10

Eventually, the main method has no more code to run. When this happens, the main frame gets popped from the stack, and the program ends.

Call Stack
-
-
-
-

The call stack has a limited size that varies based on the Ruby implementation. That size is usually sufficient for more than 10000 stack entries. If the stack runs out of room, you will see a SystemStackError exception.

If you need a slightly more visual approach, take 10 minutes to watch this video .

Please note that this video uses JavaScript, not Ruby. However, the JavaScript portions of the video are very basic, and shouldn't be too difficult to understand given your current Ruby knowledge. Most importantly, don't try to learn JavaScript at this point - that comes later.

The chief difference between the JavaScript shown in the video and what you know of Ruby is that JavaScript uses the term "function" in much the same way as Ruby uses the term "method". For our purposes, they represent the same concept. Syntax-wise, JavaScript uses the function keyword to define functions, while Ruby uses the def keyword to define methods.

Methods are a major part of programming in Ruby. Knowing what a method is and what operations it is performing is crucial to your development as a Ruby programmer. You'll be using them constantly, in programs both big and small. Knowing the difference between puts and return will help you avoid a common pitfall that we see many beginners struggle with. Finally, knowing how and when to use method chaining will help you better read code and let you write more succinct code. But watch out for those nils. Let's get into some exercises and put this knowledge to use!

Write a program that prints a greeting message. This program should contain a method called greeting that takes a name as its parameter and returns a string.

Video Walkthrough

Please register to play this video

What do the following expressions evaluate to? That is, what value does each expression return?

Write a program that includes a method called multiply that takes two arguments and returns the product of the two numbers.

What will the following code print to the screen?

It will not print anything to the screen.

1) Edit the method definition in exercise #4 so that it does print words on the screen. 2) What does it return now?

What does the following error message tell you?

You are calling a method called calculate_product that requires two arguments, but you are only providing one.

ruby def assignment

If the Ruby interpreter encounters a line beginning with =begin , it skips that line and all remaining lines through and including a line that begins with =end .

The string expressions begin with % are the special form to avoid putting too many backslashes into quoted strings. The %q/STRING/ expression is the generalized single quote. The %Q/STRING/ (or %/STRING/ ) expression is the generalized double quote. Any non-alphanumeric delimiter can be used in place of / , including newline. If the delimiter is an opening bracket or parenthesis, the final delimiter will be the corresponding closing bracket or parenthesis. (Embedded occurrences of the closing bracket need to be backslashed as usual.)

Backslash notation

\t tab(0x09) \n newline(0x0a) \r carriage return(0x0d) \f form feed(0x0c) \b backspace(0x08) \a bell(0x07) \e escape(0x1b) \s whitespace(0x20) \nnn character in octal value nnn \xnn character in hexadecimal value nn \cx control x \C-x control x \M-x meta x (c | 0x80) \M-\C-x meta control x \x character x itself

The %x/STRING/ is the another form of the command output expression.

The %r/STRING/ is the another form of the regular expression.

^ beginning of a line or string $ end of a line or string . any character except newline \w word character[0-9A-Za-z_] \W non-word character \s whitespace character[ \t\n\r\f] \S non-whitespace character \d digit, same as[0-9] \D non-digit \A beginning of a string \Z end of a string, or before newline at the end \z end of a string \b word boundary(outside[]only) \B non-word boundary \b backspace(0x08)(inside[]only) [ ] any single character of set * 0 or more previous regular expression *? 0 or more previous regular expression(non greedy) + 1 or more previous regular expression +? 1 or more previous regular expression(non greedy) {m,n} at least m but most n previous regular expression {m,n}? at least m but most n previous regular expression(non greedy) ? 0 or 1 previous regular expression | alternation ( ) grouping regular expressions (?# ) comment (?: ) grouping without backreferences (?= ) zero-width positive look-ahead assertion (?! ) zero-width negative look-ahead assertion (?ix-ix) turns on (or off) `i' and `x' options within regular expression. These modifiers are localized inside an enclosing group (if any). (?ix-ix: ) turns on (or off) `i' and `x' options within this non-capturing group.

line-oriented string literals (Here document)

There's a line-oriente form of the string literals that is usually called as `here document'. Following a << you can specify a string or an identifier to terminate the string literal, and all lines following the current line up to the terminator are the value of the string. If the terminator is quoted, the type of quotes determines the type of the line-oriented string literal. Notice there must be no space between << and the terminator.

If the - placed before the delimiter, then all leading whitespcae characters (tabs or spaces) are stripped from input lines and the line containing delimiter. This allows here-documents within scripts to be indented in a natural fashion.

The local variables assigned first time in the blocks are only valid in that block. They are called `dynamic variables.' For example: i0 = 1 loop { i1 = 2 print defined?(i0), "\n" # true print defined?(i1), "\n" # true break } print defined?(i0), "\n" # true print defined?(i1), "\n" # false

self the receiver of the current method nil the sole instance of the Class NilClass(represents false) true the sole instance of the Class TrueClass(typical true value) false the sole instance of the Class FalseClass(represents false) __FILE__ the current source file name. __LINE__ the current line number in the source file.

%w expressions make creation of the arrays of strings easier. They are equivalent to the single quoted strings split by the whitespaces. For example:

is equivalent to ["foo", "bar", "baz"] . Note that parenthesis right after %s is the quote delimiter, not usual parenthesis.

If the last argument expression preceded by & , the value of the expression, which must be a Proc object, is set as the block for the calling method.

Some methods are private , and can be called from function form invocations (the forms that omits receiver).

There may be no space between operators and = .

Multiple assignment acts like this:

Behavior of the === method varies for each Object. See docutmentation for each class.

The word ` raise ' is not the reserved word in Ruby. raise is the method of the Kernel module. There is an alias named fail .

If an exception occurs in the begin body, the rescue clause with the matching exception type is executed (if any). The match is done by the kind_of? . The default value of the rescue clause argument is the StandardError , which is the superclass of most built-in exceptions. Non-local jumps like SystemExit or Interrupt are not subclass of the StandardError .

The begin statement has an optional else clause, which must follow all rescue clauses. It is executed if the begin body does not raise any exception.

For the rescue clauses, the error_type is evaluated just like the arguments to the method call, and the clause matches if the value of the variable $! is the instance of any one of the error_type of its subclass. If error_type is not class nor module, the rescue clause raises TypeError exception.

If retry appears in the iterator, the block, or the body of the for expression, restarts the invocation of the iterator call. Arguments to the iterator is re-evaluated.

Registers the initialize routine. The block followed after BEGIN is evaluated before any other statement in that file (or string). If multiple BEGIN blocks are given, they are evaluated in the appearing order.

The BEGIN block introduce new local-variable scope. They don't share local variables with outer statements.

The BEGIN statement can only appear at the toplevel.

Registers finalize routine. The block followed after END is evaluated just before the interpreter termination. Unlike BEGIN , END blocks shares their local variables, just like blocks.

The END statement registers its block only once at the first execution. If you want to register finalize routines many times, use at_exit .

The END statement can only appear at the toplevel. Also you cannot cancel finalize routine registered by END .

Defines the new method. Method_name should be either identifier or re-definable operators (e.g. ==, +, -, etc.). Notice the method is not available before the definition. For example: foo def foo print "foo\n" end will raise an exception for undefined method invoking.

The return value of the method is the value given to the return , or that of the last evaluated expression.

In addition, the methods named initialize are always defined as private methods.

Making aliases for the numbered global variables ( $1 , $2 ,...) is prohibited. Overriding the builtin global variables may cause serious problems.

The letter A styled as Alchemists logo.

  • Ruby Method Parameters And Arguments

Avatar of Brooke wrapped in a grey scarf and wearing a black jacket with a red zipper against a slightly blurred background of fall colors of mainly orange leaves.

The distinction between method parameters and arguments  — as shown in the screenshot above — is probably familiar to most Ruby engineers. If not, here’s a quick explanation on the distinction between the two as pulled from the Marameters gem:

Parameters : Represents the expected values to be passed to a method when messaged as defined when the method is implemented. Example: def demo one, two: nil . Arguments : Represents the actual values passed to the method when messaged. Example: demo 1, two: 2 .

With the above in mind, this article will dig deeper into how parameters and arguments work in Ruby since there are subtleties that might not be obvious unless you’re doing more complex logic and/or metaprogramming.

No Keywords

Keyword fallbacks, keyword overrides, parenthesis, procs and lambdas, argument forwarding, destructuring.

There is important terminology to be aware of when defining method parameters and later passing arguments to the same method. I’ve split the terminology into several sections starting at a high level and working further down into specifics.

Basic parameters are those which you are most likely to be aware of and use on a daily basis. Consider the following code where all possible parameters are used:

The above leverages the basic parameters you can define for a method in order of precedence . If we inspect the method’s parameters and then use Amazing Print to render the response, things become more clear since we get an array of tuples (i.e. kind and name ):

The kinds of parameters allowed can be split into three categories:

Positionals : Positional parameters are more strict, less descriptive, and require arguments to be passed in a specific order, otherwise you’ll get an ArgumentError . There are three types of positional arguments you can use:

req : A required parameter with no default value.

opt : An optional parameter that always has a default value and should only be defined after a required positional parameter.

rest : Optional parameters — also known as single splats ( * ) — which can be any number of parameters after your optional positionals. ⚠️ Heavy use of this parameter is considered a code smell because, when unchecked, can get quite large so use with care or avoid altogether.

Keywords : Keyword parameters are more descriptive than positional parameters and have a similar breakdown to positional parameters:

keyreq : A required parameter with no default value.

key : An optional parameter that always has a default value and should only be defined after a required keyword parameter.

keyrest : Optional parameters — also known as double splats ( ** ) — which can be any number of parameters that come after your optional keywords. ⚠️ Heavy use of this parameter is considered a code smell because, when unchecked, can get quite large so use with care or avoid altogether.

Block : You can only define a single block parameter and must be in the last position. In our case, the block parameter is explicitly named seven even though most people tend to use block as the parameter name. A deeper dive into blocks is out of scope for this article but you can learn more about them in my Ruby Function Composition article. In the meantime, here’s a quick explanation:

Implicit : All methods can implicitly accept a block. Example: demo { "Example." } . Implicit blocks make for an elegant design when coupled with block_given? in order to yield to the block passed to your method.

Explicit : If you want to explicitly reference a block, then you must name it. Example: def demo(&block) . Explicit blocks are great when you need to use the block directly without the need to check if a block has been implicitly defined.

Anonymous : Anonymous blocks were first introduced in Ruby 3.1.0 and are great for forwarding to another method without needing to name them first. Example: def demo(&) .

Argument forwarding was first introduced in Ruby 2.7.0 . The syntax only requires three dots (ellipses) to use. Example:

What’s important to highlight is that this resolves to the following:

Uses :rest as the kind and :* as the name (i.e. anonymous single splat).

Uses :keyrest as the kind and :** as the name (i.e. anonymous double splat).

Uses :block as the kind and :& as the name (i.e. anonymous block).

Argument forwarding was enhanced with leading arguments in Ruby 3.0.0 . Example:

While the above is a simple example that only uses a leading required positional parameter, you can definitely lead with both required and optional positional arguments as well. Keywords and blocks are not allowed, though, and will cause a syntax error.

The kinds and names of these parameters are important because they allow you to pattern match and dynamically distinguish between a method using forwarding, anonymous splats/blocks, or named parameters.

There are three kinds of parameter splats: forwards , anonymous , or named . You’ve already seen how forwarding works and to illustrate further, the following table provides a visual breakdown of the different kinds of splats in Ruby 3.2.0 and higher:

Kind Signature Parameters

Forwards

Anonymous

Named

Prior to the release of Ruby 3.2.0 , forwarding of bare splats wasn’t supported which meant a method signature of def demo(*, **) would result in the following parameters: [[:rest], [:keyrest]] . With Ruby 3.2.0 and higher, using forwarded or anonymous parameters always results in identical parameters as emphasized above: [[:rest, :*], [:keyrest, :**]] .

We’ll dive into the details of each kind of parameter next.

Anonymous splats — also known as bare splats — are denoted by use of a single splat ( * ), double splat ( ** ), and/or the bare block ( & ). The single splat is an Array while the double splat is a Hash . Here’s an example:

Prior to the release of Ruby 3.2.0 , bare splats never had a name so you’d only get information about the kind of splat which meant you couldn’t do much else with them. With Ruby 3.2.0 and higher, bare splats can be forwarded in addition to other benefits:

You can use super  — as shown in the example above — to pass the splatted arguments upwards for further processing.

You can forward the single, double, and/or block splat to another method. Example: def demo(*, **, &) = my_method(*, **, &) .

You can gobble positional and/or keyword arguments into a black hole so-to-speak so they are never used. This can be handy when coupled with the Null Object Pattern where you ignore the incoming splatted arguments entirely.

💡 Despite anonymous splats being…​well…​anonymous, you can debug them by splatting them into an empty array, hash, or proc accordingly. Don’t use this in production, though. Example:

With the positional and keyword arguments, you get immediate inspection. With the block, you get partial inspection because you can see if you are dealing with a proc or a lambda. Alternatively, you could call the block for deeper inspection:

In contrast to anonymous splats, we can use named splats as well. Example:

As you can see, we get kind and name information which means we can make use of them within the method like any other argument.

The difference between forwards , anonymous and named splats is important to know when inspecting a method’s behavior or dynamically building a list of arguments for messaging.

Single and double splats can be implicitly coerced into an Array and Hash , respectively, when given no arguments. Example:

Behavior is different when passing nil , though. Example:

At the moment — and unlike an Array  —  **nil can’t be implicitly cast into a Hash and will raise a TypeError . Starting in Ruby 3.4.0, this is fixed so you can pass *nil and **nil as arguments and, implicitly, get an empty array and hash.

The post parameter is obscure, rare, and awkward when you see it in the wild that is a required positional parameter that comes after an optional positional parameter. Example:

In very rare cases, post parameters can be useful but, in general, they suffer from the following:

Harder to read, surprising, and uncommon to see in actual code.

You will get a RuboCop Style/OptionalArguments error if attempting to use this parameter.

You can’t use a single splat positional argument after a post parameter is defined. Although, you can use required, optional, and double splat keyword parameters as well as a block.

Performance-wise, Ruby can’t optimize post parameters like it can for required and optional parameters.

This keyword parameter — though, rarely used — comes in handy when you don’t want to support any keywords. Example:

Generally, you combine the nokey parameter with positional parameters. Example:

Once the nokey parameter is defined, you can’t provide any required or optional parameters (blocks are always allowed, though) as the following syntax is invalid:

Parameters are evaluated from left to right , which means you can have a method signature using either positional or keyword parameters. Consider the following:

Notice you can pass in the "Test" value either as a positional argument or keyword argument and get the same result. In the case of using a positional argument, the value will become the default value for the keyword parameter. This can be handy when wanting to use a positional parameter as a fallback for your keyword parameter or wanting to refactor using keyword parameters instead of positional parameters. While this is worth knowing, there are several caveats to watch out for since this can lead to problematic code:

When passing in both a positional and keyword argument, the keyword argument will take precedence due to being evaluated last. For example, using demo "One", name: "Two" will print the value of "Two" instead of "One" .

When wanting to convert multiple positional parameters into keyword parameters, you can end up with a very long method signature that will quickly violate the rule of three for maximum number of parameters used.

You should add a deprecation warning when the positional parameter is set to encourage people to update their code to using the keyword arguments instead. This will allow people to upgrade while also setting a date in which you delete positional parameter support to keep code complexity at a minimum.

There are several Ruby Keywords . In rare situations, you might want to use one of those keywords as a method parameter which will cause a syntax error. For example, the following errors because both the begin and end keywords conflict with the built-in language keywords:

You can workaround this situation by using binding . Here’s how to rewrite the above to solve the problem:

You can clean this up further by using the Refinements gem:

If refining isn’t your cup of team, you could use hash pinning:

While hash pinning might be slightly awkward, there can be a performance boost as shown in these benchmarks .

While the above provides a working solution, there are important caveats to be aware of:

This solution is only possible when using keyword parameters and does not work for positional parameters.

There is precedence for this use case but even the core language is not the best teacher so tread with caution.

Applying this solution to your own code should be done with caution because heavy use of binding can get unwieldy and cumbersome quickly. Granted, this can be useful in Domain Specific Languages (DSLs) or adding a touch of syntactic sugar to your method signatures in rare situations but you’d only want to reach for this when all other options have been exhausted.

As an obscure syntactical oddity, you can wrap a required positional parameter in parenthesis as a way to bypass being able to pass a tuple (or larger) as a destructured required parameter. The inner parenthesis is critical to making this work and only works for required parameters. Example:

Notice that you only get :req as the kind but no name. In truth, you have two parameter names (i.e. one and two ) — each destructured — but the #parameters method can’t show you that since it has no way to represent multiple names for a kind. Here’s a more complete illustration:

This usage is more an antipattern because the required positional parameter (array) is subtle and will cause people to have a hard time reading and understanding the code. At the same time, this does give you a way to define the shape of the required positional parameter. Other complications, such as shared assignment, is another concern. Take the following:

In general — and due to these complications — use of parenthesis is not a recommended practice.

Ruby primitives — such as String , Integer , Struct , and so forth — are written in C, not Ruby. Sadly, this means asking for a primitive’s parameters will give you false information. A good example is using an inline Struct :

If you use Structs a lot — or any primitive written in C — you know this information is incorrect because a struct can accept both positional and keyword arguments. The problem is the argument conversion is done in C, not Ruby. This is another aspect of Ruby where asking for a method’s parameters won’t help you but is important to be aware of. There is a long standing Ruby Issue , if fixed, would solve this problem and lead to more informative parameter information.

One trick to solving this situation is via a .for method (or whatever method you deem is an appropriate shim). Example:

Notice how we get better parameter information — well, minus the block parameter — which tells the truth in terms of being able to use positional or keyword parameters. To take this a step further by being specific, use splats instead. Example:

In all of these examples, you now have more accurate parameter information via .for instead of .new which comes in handy when dynamically messaging these objects and using a gem like Marameters , for example.

Starting with Ruby 3.2.0 , support was added for proc parameters to be converted into lambda parameters for quick proc to lambda conversion. Example:

Notice, by passing lambda: true to the #parameters method, the proc will answer back parameters as if the proc was a lambda since the first parameter would be required for a lambda but optional for a proc. This provides a way for you to dynamically convert a proc into a lambda.

One caveat to be aware of with procs/lambas is: argument forwarding. Currently, argument forwarding isn’t possible. Consider the following:

Anonymous argument forwarding might be supported in the future so keep an eye on future versions of Ruby to see how this evolves.

To understand arguments, we’ll need to a more…​introspective…​implementation:

Keep this implementation in mind or scroll back, when needed, to reread since this implementation will be referenced repeatedly.

With the above implementation, the minimal set of arguments we could use are:

All seven arguments — a few of which are either nil or empty since they are optional — are printed to the console. This output can be further explained as follows:

req: a : This positional argument was required so we had to pass in a value (i.e. :a ).

opt: b : This positional argument was optional so the default value of :b was answered back.

rest: [] : This positional argument was optional too but since we gave it nothing, we got an empty array due to single splats always resolving to an array.

keyreq: d : This keyword argument was required so we had to pass in a value (i.e. :d ).

key: e : This keyword argument was optional so the default value of :e was answered back.

keyrest: {} : This keyword argument was optional too but since we gave it nothing, we got an empty hash due to double splats always resolving to a hash.

block: nil : We didn’t supply a block so we got back nil in this case since blocks are optional since they can be implicitly or explicitly used.

To contrast the minimal set of arguments passed to the .demo method, we can also pass in a maximum — loosely speaking — set of arguments. Example:

This time we have a lot more arguments passed in and printed out to the console. We can break this down further highlighting the differences:

rest: [:y, :z] : Any number of optional positional arguments could have been supplied here but only :y and :z were used in this case.

keyrest: {:y ⇒ 10, :z ⇒ 20} : Any number of optional keyword arguments could have been supplied here but only y: 10 and z: 20 were used in this case.

block: #<Proc:0x000000010d1cbc78> : Since we passed in an explicit block, you can see it’s pass through and printed out as well.

With the basic use of arguments in mind, we can now expand into more advanced usage.

Argument splats — as mentioned earlier when first discussing parameters — can be categorized as follows:

Single (array): Can be bare (i.e. * ) or named (example: *positionals ).

Double (hash): Can be bare (i.e. ** ) or named (example: **keywords ).

Block (proc): Can be bare (i.e. & ) or named (example: &block ).

When these are arguments are passed in, they will be automatically coerced. For simplicity, I’m using named arguments but the same applies for bare arguments:

Single (array): Evaluates to *positionals.to_a . This behavior is definitely surprising and an oddity because you’d expect the implicit #to_ary to be called instead of the explicit #to_a which is inconsistent with how double and block arguments work.

Double (hash): Evaluates to **keywords.to_hash .

Block (proc): Evaluates to &block.to_proc .

💡 For more information on proper use of implicit and explicit casting, see my Ruby Antipatterns articles for details.

You want to splat your arguments when you need to destruct your arrays, hashes, or proc into a list of arguments or can’t directly pass them to a method but need to dynamically build up the arguments instead. With the .demo method implementation from earlier — and using our knowledge of positional, keyword, and block parameters — we can pass single and double splats along with a block to this method as follows:

Notice the above’s output is identical to our earlier example (except for the new Proc instance) where we passed in a maximum set of arguments. What’s different is we’ve categorized the positional, keyword, and block arguments. Single and double splats makes this easier. To take this a step further — and assuming the argument list was dynamically assigned to local variables — the code then becomes more descriptive:

Keep in mind that single and double splats must be used when destructuring arrays and hashes for messaging purposes. For example, the following doesn’t work because you have to explicitly use single or double splats with your arguments:

We’ll learn more about splats in message delegation next.

The super keyword is one of several Ruby Keywords that allows you to forward arguments to the parent method when using inheritance . The super keyword deserves special mention since behavior can differ based on the types of arguments used. Consider this basic implementation:

The above shouldn’t be surprising when forwarding arguments from the child to the parent because super  — without explicit arguments or parenthesis —  implicitly forwards the same arguments. Same goes if you modify the arguments before calling super :

However, using parenthesis, will prevent super from forwarding any arguments:

As you can see, the positional and keyword arguments were not forwarded but notice the block was! This is because super implicitly forwards the block whether you like it or not. To prevent this behavior, use super(&nil) :

Message Delegation

At this point, we are now primed to discuss message delegation which is where parameter and argument compatibility gets interesting. To set the stage, we’ll expand upon our earlier implementation by using the following snippet of code:

The major changes are that:

The above is written as a Bundler Inline script so you can tinker with the code locally.

Monads are used. Don’t worry about needing to know how to use monads. You only need to care about the destructuring of arguments in the #fifth_example method. I’ll explain, shortly.

The Marameters gem is introduced as well which provides a convenient way to obtain method parameter information. We’ll talk about this gem in the final example.

Now we can focus on the #*_example methods in terms of argument forwarding, splats, and destructured arguments.

Argument forwarding (i.e. ... ) makes passing of arguments less of a hassle in some cases. To see argument forwarding in action, here’s how make use of the above code snippet:

By now, the output should come as no surprise since all we’ve done is forward all arguments from the #first_example method to the .demo method by adding a leading argument to specify the :demo method when using #public_send . This is a elegant and the most succinct of all examples.

Should argument forwarding not be desired or needed, we can always fall back to using splats as provided by the second and third examples. We’ll start with the second example:

As you can see from the output, there is no change between the first and second example. What might be surprising is you can use anonymous single splat, double splat, and block parameters. This is new in Ruby 3.2.0 . If we want to be more verbose, we can name our arguments as done in the third example:

Again, no change in output as we get the same desired result but this time we’ve given our single splat, double splat, and block arguments a name.

A subtle distinction is that you must use splats in your parameters and continue to use splats when delegating the arguments, otherwise you’ll end up with nested arrays and/or hashes. Here are a few examples of the errors you’ll get when the code is modified without splats:

Last, but not least, is argument destructuring. Both the third and fourth example methods tackle this in similar ways by wrapping of all arguments within a single array. Consider the following:

In this case, the single array argument is composed of positional, keyword, and block elements which are destructured into positionals , keywords , block local variables so they can be passed on using a single splat, double splat, and ampersand. There is no way to dynamically use * , ** , or & unless you evaluate the expression as a string. Example:

Instance evaluation would be an unnecessary — and less performant — so prefixing the local variables with * , ** , and & is better. A similar pattern is used when passing a monad as an argument to the fourth method:

The key difference is that we can use the block parameters to automatically destructure into positional, keyword, and block arguments needed for message passing. 🎉

Sadly, we can’t use argument forwarding in block parameters. It would be nice but is currently not possible.

At the start of this article, I alluded to the Marameters gem. Specifically, the .categorize method used in the #sixth_example method. Using everything we’ve discussed above, Marameters will ensure the arguments align as required by the method’s parameters. Example:

As you can see, the output is the same as all of our earlier examples. No change and no surprise. However — and this is important to be compatible with Method#parameters  — we use a single array argument which means all elements of the array must be in the right position to match the equivalent positions of the method’s parameters.

The Marameters gem can be handy when you want to build an array of arguments for forwarding to a method. Definitely check out the gem’s documentation for more details.

During the course of this article we’ve learned how to parse a methods’s parameters, along with the kinds of parameters you can use in a method signature, and how the arguments passed to the method are parsed based on the defined parameters. We’ve also learned, briefly, how to leverage the Marameters gem to dynamically build a list of method arguments. Hopefully, with this knowledge, you’ll be able to leverage better use of parameters and arguments in your own implementations too. Enjoy!

Ruby Programming/Syntax/Operators

  • 1.1 Complete List and Precedence
  • 1.2 Other operators
  • 1.3 Assignment
  • 2.1 Local Scope
  • 2.2 Global scope
  • 2.3 Instance scope
  • 2.4 Class scope
  • 3 Default scope
  • 4 Local scope gotchas
  • 5 Logical And
  • 6 Logical Or
  • 7 References

Complete List and Precedence

Operator Name/meaning Arguments Precedence 1] Association
! Boolean NOT Unary 1 Right
~ Bitwise complement Unary 1 Right
+ Unary plus (no effect) Unary 1 Right
** Exponentiation Binary 1 Right
- Unary minus (reverse sign) Unary 2 Right
* Multiplication Binary 3 Left
/ Division Binary 3 Left
% Modulo (remainder) Binary 3 Left
+ Addition or concatenation Binary 4 Left
- Subtraction Binary 4 Left
<< Bitwise shift left or append (<< and <<- are also used in ) Binary 5 Left
>> Bitwise shift right Binary 5 Left
& Bitwise AND Binary 6 Left
| Bitwise OR Binary 7 Left
^ Bitwise XOR Binary 7 Left
< Less-than Binary 8 Left
<= Less-than or equal-to Binary 8 Left
> Greater-than Binary 8 Left
>= Greater-than or equal to Binary 8 Left
== Equal (evaluate to the same value) Binary 9 N/A
=== "Case equality", "case subsumption" or "three equals" operator. if B is a member of the set of A. Operation varies considerably depending on the data types of A and B. Binary 9 N/A
!= Not equal Binary 9 N/A
=~ Pattern match Binary 9 N/A
!~ Negative pattern match Binary 9 N/A
<=> A <=> B evaluates to -1, 0, or 1; if A is less-than, equal-to, or greater-than B, respectively Binary 9 N/A
&& Boolean AND Binary 10 Left
|| Boolean OR Binary 11 Left
.. Range creation, boolean flip-flop Binary 12 N/A
... Open-ended range creation, boolean flip-flop Binary 12 N/A
?: A?B:C evaluates to B if A is true, or C if A is false Trinary 13 Right
rescue Modifier for catching exceptions e.g. Binary 14 Left
= Assignment Binary 15 Right
**= A **=B does A = A ** B Binary 15 Right
*= A *=B does A = A * B Binary 15 Right
/= A /=B does A = A / B Binary 15 Right
%= A %=B does A = A % B Binary 15 Right
+= A +=B does A = A + B Binary 15 Right
-= A -=B does A = A – B Binary 15 Right
<<= A <<=B does A = A << B Binary 15 Right
>>= A >>=B does A = A >> B Binary 15 Right
&&= A &&=B assigns B to A if A is true or not nil Binary 15 Right
&= A &=B does A = A & B Binary 15 Right
||= A ||=B assigns B to A if A is nil or false Binary 15 Right
|= A |= B does A = A | B Binary 15 Right
^= A ^=B does A = A ^ B Binary 15 Right
defined? nil if the expression cannot be evaluated (e.g. unset variable) Unary 16 N/A
not Boolean NOT Unary 17 Right
and Boolean AND Binary 18 Left
or Boolean OR Binary 18 Left
if Conditional, e.g. Binary 19 N/A
unless Negative conditional, e.g. Binary 19 N/A
while Loop conditional, e.g. Binary 19 N/A
until Loop conditional, e.g. Binary 19 N/A

Higher precedence (lower number in the above table) operators have their immediate arguments evaluated first. Precedence order can be altered with () blocks. For example, because * has higher precedence than +, then: 1 + 2 * 3 == 7 (1 + 2) * 3 == 9

Association direction controls which operators have their arguments evaluated first when multiple operators with the same precedence appear in a row. For example, because - has left association:

1 – 2 – 3 == (1 – 2) – 3 == -1 – 3 == -4

instead of:

1 – 2 – 3 == 1 – (2 – 3) == 1 - -1 == 0

Because ** has right association:

2 ** 3 ** 2 == 2 ** (3 ** 2) == 2 ** 9 == 512

2 ** 3 ** 2 == (2 ** 3) ** 2 == 8 ** 2 == 64

{} blocks have lower precedence than the above operators, followed by do/end blocks. Array accesses with [] can be thought of as having a higher precedence than any above operator.

The operators ** through !~ can be overridden (defined for new classes, or redefined for existing operations).

Note that rescue, if, unless, while, and until are operators when used as modifiers in one-liners (as in the above examples) but can also be used as keywords.

Other operators

The dot operator . is used for calling methods on objects, also known as passing a message to the object.

Ruby 2.3.0 introduced the safe navigation operator &. , also known as the "lonely operator". [ 2 ] This allows replacing

An equivalent .dig() method was introduced for hashes and arrays:

are safer versions of:

The safe navigation operator will raise an error if a requested method, key, or index is not available; unlike the technique of using try() for this purpose, which will return nil. [ 3 ]

Yukihiro Matsumoto considered ! ?. and .? before settling on &. because: [ 4 ]

  • ?. conflicts with *?
  • ?. is used by other languages, thus .? is confusingly similar but different
  • ! conflicts with "not" logic
  • ? is already used by convention for functions that return booleans
  • &. is reminiscent of the && syntax the operator is replacing

!! is sometimes seen, but this is simply the ! operator twice. It is used to force the following expression to evaluate to a boolean. This technique is considered non-idiomatic and poor programming practice, because there are more explicit ways to force such a conversion (which is rarely needed to begin with).

Assignment in Ruby is done using the equal operator "=". This is both for variables and objects, but since strings, floats, and integers are actually objects in Ruby, you're always assigning objects.

Self assignment

A frequent question from C and C++ types is "How do you increment a variable? Where are ++ and -- operators?" In Ruby, one should use x+=1 and x-=1 to increment or decrement a variable.

Multiple assignments

Conditional assignment

Operator ||= is a shorthand form that closely resembles the expression: [ 5 ]

Operator ||= can be shorthand for code like:

In same way &&= operator works:

Operator &&= is a shorthand form of the expression:

In Ruby there's a local scope, a global scope, an instance scope, and a class scope.

Local Scope

This error appears because this x(toplevel) is not the x(local) inside the do..end block the x(local) is a local variable to the block, whereas when trying the puts x(toplevel) we're calling a x variable that is in the top level scope, and since there's not one, Ruby protests.

Global scope

This output is given because prefixing a variable with a dollar sign makes the variable a global.

Instance scope

Within methods of a class, you can share variables by prefixing them with an @.

Class scope

A class variable is one that is like a "static" variable in Java. It is shared by all instances of a class.

Here's a demo showing the various types:

This will print the two lines "kiwi" and "kiwi told you so!!", then fail with a undefined local variable or method 'localvar' for #<Test:0x2b36208 @instvar="kiwi"> (NameError). Why? Well, in the scope of the method print_localvar there doesn't exists localvar, it exists in method initialize(until GC kicks it out). On the other hand, class variables '@@classvar' and '@instvar' are in scope across the entire class and, in the case of @@class variables, across the children classes.

Class variables have the scope of parent class AND children, these variables can live across classes, and can be affected by the children actions ;-)

This new child of Test also has @@classvar with the original value newvar.print_classvar. The value of @@classvar has been changed to 'kiwi kiwi waaai!!' This shows that @@classvar is "shared" across parent and child classes.

Default scope

When you don't enclose your code in any scope specifier, ex:

it affects the default scope, which is an object called "main".

For example, if you had one script that says

and other_script.rb says

They could share variables.

Note however, that the two scripts don't share local variables.

Local scope gotchas

Typically when you are within a class, you can do as you'd like for definitions, like.

And also, procs "bind" to their surrounding scope, like

However, the "class" and "def" keywords cause an *entirely new* scope.

You can get around this limitation by using define_method, which takes a block and thus keeps the outer scope (note that you can use any block you want, to, too, but here's an example).

Here's using an arbitrary block

Logical And

The binary "and" operator will return the logical conjunction of its two operands. It is the same as "&&" but with a lower precedence. Example:

The binary "or" operator will return the logical disjunction of its two operands. It is the same as "||" but with a lower precedence. Example:

  • ↑ http://ruby-doc.org/core-2.4.0/doc/syntax/precedence_rdoc.html
  • ↑ https://www.ruby-lang.org/en/news/2015/12/25/ruby-2-3-0-released/
  • ↑ http://blog.rubyeffect.com/ruby-2-3s-lonely-operator/
  • ↑ https://bugs.ruby-lang.org/issues/11537
  • ↑ http://www.rubyinside.com/what-rubys-double-pipe-or-equals-really-does-5488.html

ruby def assignment

  • Book:Ruby Programming

Navigation menu

  • Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
  • Advertising & Talent Reach devs & technologists worldwide about your product, service or employer brand
  • OverflowAI GenAI features for Teams
  • OverflowAPI Train & fine-tune LLMs
  • Labs The future of collective knowledge sharing
  • About the company Visit the blog

Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Get early access and see previews of new features.

Dynamic Class Definition WITH a Class Name

How do I dynamically define a class in Ruby WITH a name?

I know how to create a class dynamically without a name using something like:

But you can't specify a class name. I want to create a class dynamically with a name.

Here's an example of what I want to do but of course it doesn't actually work. (Note that I am not creating an instance of a class but a class definition)

Actual output:

Desired output:

======================================================

Answer: A totally dynamic solution using sepp2k's method

  • metaprogramming

Joshua Pinter's user avatar

  • 1 I don't really get what you want to accomplish. There is a class TestEval2, you can do test_eval2 = TestEval2.new afterwards. And: class A ... end always yields nil, so your output is ok I guess ;-) –  Philip Commented Nov 6, 2010 at 14:34
  • It's for a TDD test step. I need to create a test class dynamically and then reference its name because that's how it will be used in the wild. sepp2K got it right. –  Mike Bethany Commented Nov 6, 2010 at 14:54
  • 2 @Philip: class A ... end does not evaluate to nil , it evaluates to the value of the last expression evaluated inside it, just like every other compound expression (blocks, methods, module definitions, expression groups) in Ruby. It just so happens that in many class definition bodies, the last expression is a method definition expression, which evaluates to nil . But it is sometimes useful to have a class definition body evaluate to a specific value, e.g. in the class << self; self end idiom. –  Jörg W Mittag Commented Nov 6, 2010 at 15:07

4 Answers 4

The name of a class is simply the name of the first constant that refers to it.

I.e. if I do myclass = Class.new and then MyClass = myclass , the name of the class will become MyClass . However I can't do MyClass = if I don't know the name of the class until runtime.

So instead you can use Module#const_set , which dynamically sets the value of a const. Example:

sepp2k's user avatar

  • 1 Thank you. This helped me here: github.com/validates-email-format-of/validates_email_format_of/… –  Isaac Betesh Commented Aug 15, 2014 at 5:32
  • 3 Wow. Seems very odd to me that (constant) assignment has this side effect. –  Daniel Lubarov Commented Dec 19, 2014 at 21:33
  • For some reason this works in development for me, but not in production –  sandre89 Commented Dec 14, 2016 at 12:31
  • I've tried to set the constant on the new class itself, to no avail. With Object it works. Thanks. –  John Dvorak Commented Mar 27, 2017 at 16:35

I've been messing around with this too. In my case I was trying to test extensions to ActiveRecord::Base. I needed to be able to dynamically create a class, and because active record looks up a table based on a class name, that class couldn't be anonymous.

I'm not sure if this helps your case, but here's what I came up with:

As far as ActiveRecord is concerned, defining self.name was enough. I'm guessing this will actually work in all cases where a class cannot be anonymous.

(I've just read sepp2k's answer and I'm thinking his is better. I'll leave this here anyway.)

Chris Hough's user avatar

  • 2 Incidentally, you COULD just set the table name for the class explicitly, like this: self.table_name = "my_things" –  Earl Jenkins Commented Oct 31, 2017 at 21:24
  • 1 @EarlJenkins If there are associations defined within such class (e.g. belongs_to), self.name is necessary otherwise #demodulize will fail on nil while trying to follow association :( At least that is what happened to me with Rails 5.2.3. –  mlt Commented Nov 26, 2019 at 3:56

I know this is a really old question, and some other Rubyists might shun me from the community for this, but I am working on creating a very thin wrapper gem that wraps a popular java project with ruby classes. Based on @sepp2k's answer, I created a couple helper methods because I had to do this many, many times in one project. Note that I namespaced these methods so that they were not polluting some top-level namespace like Object or Kernel.

To use these methods (note that this is JRuby):

This allows me to create a JRuby gem that uses the Java project and would allow the open source community and I to decorate these classes in the future, as necessary. It also creates a more friendly namespace to use the classes in. Since my gem is a very, very thin wrapper, I had to create many, many subclasses and modules to extend other modules.

As we say at J.D. Power, "this is apology-driven development: I'm sorry".

WattsInABox's user avatar

How aboutthe following code:

Eval doesn' retun the runtime Class object, at least on my PC it doesn't. Use Object.const_get to get the Class object.

wuyunxia's user avatar

  • 1 It can be accomplished without eval , though. With eval , you have to sanitize the input to hedge against malicious code execution. –  Pistos Commented Aug 18, 2016 at 2:52

Your Answer

Reminder: Answers generated by artificial intelligence tools are not allowed on Stack Overflow. Learn more

Sign up or log in

Post as a guest.

Required, but never shown

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy .

  • The Overflow Blog
  • The world’s largest open-source business has plans for enhancing LLMs
  • Featured on Meta
  • User activation: Learnings and opportunities
  • Site maintenance - Mon, Sept 16 2024, 21:00 UTC to Tue, Sept 17 2024, 2:00...
  • What does a new user need in a homepage experience on Stack Overflow?
  • Announcing the new Staging Ground Reviewer Stats Widget

Hot Network Questions

  • How to make a soundless world
  • Why does a capacitor act as an open circuit under a DC circuit?
  • On the history of algae classification
  • How frequently is random number generated when plotting function containing RandomReal?
  • What’s the name of this horror movie where a girl dies and comes back to life evil?
  • ordinal ω+1 explain difference from ω
  • Copyright Fair Use: Is using the phrase "Courtesy of" legally acceptable when no permission has been given?
  • Swapping front Shimano 105 R7000 34x50t 11sp Chainset with Shimano Deore FC-M5100 chainset; 11-speed 26x36t
  • If one is arrested, but has a baby/pet in their house, what are they supposed to do?
  • Multi-producer, multi-consumer blocking queue
  • What's the strongest material known to humanity that we could use to make Powered Armor Plates?
  • Looking for a short story on chess, maybe published in Playboy decades ago?
  • Definition of annuity
  • How in the world do I fix this anciently old slop sink? I am okay even with a temporary fix
  • What makes amplifiers so expensive?
  • A word like "science/scientific" that can be used for ALL academic fields?
  • What is the best way to protect from polymorphic viruses?
  • Do black holes convert 100% of their mass into energy via Hawking radiation?
  • I am an imaginary variance
  • Is Entropy time-symmetric?
  • Will "universal" SMPS work at any voltage in the range, even DC?
  • Should I be careful about setting levels too high at one point in a track?
  • Python script to renumber slide ids inside a pptx presentation
  • How to reply to a revise and resubmit review, saying is all good?

ruby def assignment

IMAGES

  1. The GCD of two numbers Using- Ruby

    ruby def assignment

  2. Exploring How To Use Def In Ruby: Essential Techniques

    ruby def assignment

  3. Using Ruby

    ruby def assignment

  4. PPT

    ruby def assignment

  5. Using Ruby

    ruby def assignment

  6. Solved 5. Consider the following Ruby class: class MyCar def

    ruby def assignment

COMMENTS

  1. assignment

    Assignment ¶ ↑. In Ruby, assignment uses the = (equals sign) character. This example assigns the number five to the local variable v: ... Assignment Methods ¶ ↑. You can define methods that will behave like assignment, for example: class C def value= (value) @value = value end end c = C. new c. value = 42.

  2. methods

    Validate. Generated by RDoc 6.7.0.. Based on Darkfish by Michael Granger. Methods ¶ ↑. Methods implement the functionality of your program. Here is a simple method definition: def one_plus_one 1 + 1 end. A method definition consists of the def keyword, a method name, the body of the method, return value and the end keyword. When called the method will execute the body of the method.

  3. assignment

    Assignment ¶ ↑. In Ruby assignment uses the = (equals sign) character. This example assigns the number five to the local variable v: ... Assignment Methods ¶ ↑. You can define methods that will behave like assignment, for example: class C def value= (value) @value = value end end c = C. new c. value = 42.

  4. Assignment

    You can mix several of the operators and assignment. To add 1 to an object you can write: a=1a+=2pa# prints 3. This is equivalent to: a=1a=a+2pa# prints 3. You can use the following operators this way: +, -, *, /, %, **, &, |, ^, <<, >>. There are also ||= and &&=. The former makes an assignment if the value was nil or false while the latter ...

  5. Ruby Assignment Syntax

    6. A silly, syntactical question: If the assignment operator is really a function, like. def value=(x) @value = x. end. without a space between the left-hand operand and the "=", then why can the assignment be made as test.value = x (with a space), but the method definition cannot be written as: def value = (x)

  6. Ruby Functions & Methods: How to Define Your Own

    def is part of Ruby's syntax, it says that we want to def ine a method. gimme_bacon is the name of the method. puts "Bacon plz." is the body of the method. end marks the end of the method definition. Defining a method only tells Ruby that you want to create it. If you want to use it then you need to call the method.

  7. Defining methods

    Here is a simple method definition: A method definition consists of the def keyword, a method name, the body of the method, return value and the end keyword. When called the method will execute the body of the method. This method returns 2. This section only covers defining methods. See also the syntax documentation on calling methods.

  8. Learning Ruby methods and how you should use them

    Learning Ruby methods allows the same piece of code to be executed many times in a program, without having to repeatedly rewrite the code. ... For example, consider this method definition: def just_assignment(number) foo = number + 3 end The value of just_assignment(2) is going to be 5 because the assignment expression evaluates to 5, therefore ...

  9. Everything You Need to Know About Ruby Constants

    Ruby Constant: A type of variable that starts with an uppercase letter & shows a warning if you try to change it. See examples & more details in this post! ... def the_method ABC = 1 end # "dynamic constant assignment" So just define your constants outside methods, typically we want to have constant definitions at the top of your class so they ...

  10. Ruby Syntax

    The character set used in the Ruby source files for the current implementation is based on ASCII. The case of characters in source files is significant. ... The constant definitions are done by assignment in the class definition body. Assignment to the constants must be done once. Changing the constant value or accessing to the non-initialized ...

  11. Official Ruby FAQ

    a = 1. method `a' called. a = 99. During the parse, Ruby sees the use of a in the first puts statement and, as it hasn't yet seen any assignment to a, assumes that it is a method call. By the time it gets to the second puts statement, though, it has seen an assignment, and so treats a as a variable.

  12. Everything You Need to Know About Ruby Operators

    The modulo assignment operator (%=) The triple equals (===) operator; Greater than (>) & less than (<) Not equals (!=) What you may not realize is that many of these operators are actually Ruby methods. This means… You can overwrite what they do & use them to define custom behavior in your own classes.

  13. methods

    Methods implement the functionality of your program. Here is a simple method definition: def one_plus_one 1 + 1 end. A method definition consists of the def keyword, a method name, the body of the method, return value and the end keyword. When called the method will execute the body of the method. This method returns 2.

  14. Ruby Method Parameters And Arguments

    Example: def demo(&block). Explicit blocks are great when you need to use the block directly without the need to check if a block has been implicitly defined. Anonymous: Anonymous blocks were first introduced in Ruby 3.1.0 and are great for forwarding to another method without needing to name them first. Example: def demo(&).

  15. Ruby Programming/Syntax/Operators

    Assignment in Ruby is done using the equal operator "=". This is both for variables and objects, but since strings, floats, and integers are actually objects in Ruby, you're always assigning objects. Examples: myvar = 'myvar is now this string' var = 321 dbconn = Mysql::new('localhost','root','password') Self assignment.

  16. How to define the assignment operator in Ruby?

    In ruby, we don't assign to an instance as you mentioned, we assign to a. variable that can hold any type. We therefore can't override the. assignment operator. BUT you can override an assignment operation… such as. class Foo. def bar= (val) @bar = val. p "I am assigning # {val} to @bar ".

  17. Ruby's Powerful Method Arguments & How To Use Them Correctly

    Hey Don, I think there are a few factors to consider, like how different are the arguments types. If all the arguments are numbers or strings, and you could easily confuse them when calling the method (like the `Point` example) then keyword arguments may be helpful.

  18. instance

    bar = "abcd". end. It isn't going to call your bar= method, it's going to create a local variable bar. So, in this case you use self to tell Ruby not to create a local variable: def other_method. self.bar = "abcd". end. The same thing applies if you want to take an argument with the name of a method: def example.

  19. ruby

    The name of a class is simply the name of the first constant that refers to it. I.e. if I do myclass = Class.new and then MyClass = myclass, the name of the class will become MyClass.However I can't do MyClass = if I don't know the name of the class until runtime.. So instead you can use Module#const_set, which dynamically sets the value of a const. Example: