Everything in Ruby is essentially an object, a thing that can be manipulated. These objects are manipulated by methods, sets of expressions that return a value.
Methods are messages that can be used to manipulate ruby objects. They are named blocks of code that define some type of behavior. Methods take an input and return an output. Often times, the input will be changed in some way to produce the desired output. As you may have noticed from previous chapters, methods are invoked with "dot notation". The method name follows the dot ( . ) and the object precedes it. For instance, let's examine the "upcase" method. This is a built in method for string objects. Remember that everything in Ruby is treated like an object, even strings.
Ruby is an extremely readable and intuitive language. The "upcase" method returns a string in all uppercase letters, as expected. Notice the use of dot notation. We call the upcase method by using a period, followed by the name of the method. We can, of course, store our string in a variable and invoke the "upcase" method in the same way.
"hello" "hello" a.upcase "HELLO"a =
The result is the same. Our string is returned to us in all capital letters.
Ruby has many built-in methods for strings, many of which we will examine in a later chapter. To give you some context, examine the following irb session:
1 a = "hello" 2 "hello" 3 a.upcase 4 "HELLO" 5 a 6 "hello" 7 a.upcase! 8 "HELLO" 9 a 10 "HELLO" 11 a 12 "HELLO" 13 a.downcase 14 "hello" 15 a.capitalize 16 "Hello"
I've introduced two new methods here, "downcase" and "capitalize". As the words imply, "downcase" returns the string in all lowercase letters while "capitalize" returns the string with only the first letter capitalized. Notice on line 5 (I've included line numbers for reference) the variable "a" returns "hello" in all lowercase letters. The "upcase" method returns the string "HELLO" as we expected but it does not change the value of the variable. On line 7, we invoke "upcase!", which is a variation of "upcase" that returns the expected result and changes the value of the variable.
Each object class in Ruby ( Integer, String, Array, Hash, Boolean, etc.) has public instance methods built-in. Many of the methods are self explanatory like "upcase" and "capitalize". Here's another example of a method that counts the number of characters in a string:
Some methods have variants that add punctuation ( ! ? ) to change the behavior of the method. Ruby uses punctuation more purposefully than any other programming language. As in English, punctuation functions as the silent language decorator that gives meaning to the words. Punctuation furthers the readability factor of Ruby, providing visual cues as to the context of the code. The exclamation point will often have the effect of changing an object like it does in the "upcase" example. The question mark indicates the method returns a boolean, a value of true or false.
It looks almost as if I'm asking ruby a question, checking to see if 4 is an integer. Ruby dutifully responds with an answer for me, true. Using punctuation in such a way is a code style convention unique to Ruby. For example, take a look at PHP:
echo "Hello World!";
PHP uses the question mark as part of the beginning and ending of scripts. However, it also uses the question mark as part of the ternary operator:
$action = (empty($_POST['action'])) ? 'default' : $_POST['action'];
Furthermore, it uses the double question mark for the null coalescing operator:
$action = $_POST['action'] ?? 'default';
Using the same punctuation in multiple ways creates confusion. Readability was not a cornerstone of PHP. Readability is interwoven into the fabric of the Ruby language.
The plus method
You've been introduced to methods earlier in this book. When we write 2 + 2 ruby returns 4. This is an example of the " + " method. Don't believe me? Check it out in irb:
When we type 2 + 2 we are invoking the " + " method and passing in an argument of 2. You can pass arguments to methods upon calling them. When passing arguments to methods, you'll normally see the argument in parenthesis. Methods can also be written using parenthesis but they are optional. For example,
"hello".upcase() will produce the same result as
"hello".upcase. The convention is to use parenthesis when supplying an argument, otherwise you can leave them off.
Let's explore methods further by creating our own sum method.
Defining a method
def sum (x, y) puts x + y end sum(3,4) # --> 7
We create a method with the def keyword, followed by the name of the method. When using the def keyword, the method must end with the end keyword. Our method will need to have data supplied to it, so we can use parameters after the method name, separated by a comma and enclosed in parenthesis.
What are parameters?
What are arguments?
Arguments consist of the data supplied to a method. The "sum" method isn't very impressive without arguments, there would be nothing to add! In the example,
2.+(2), we are passing the number 2 as an argument to the " + " method, which is invoked via dot notation.
Ruby has many methods built-in that work with different data types. As you've seen, we can also create our own named methods. Creating methods is the foundation to successfully developing with Ruby. It will become the fun part of coding. There are usually different ways to solve the same problem. Creating methods allows developers to approach the same problem in different ways. One method may be more succinct or creative than the next. How you use the tools provided by Ruby is what makes your application unique to your development style.
Another way to think about methods is that we send the "upcase" method as a message to the object "hello". This is a more accurate way of thinking as it more closely represents what is actually occuring behind the scenes. Other books on Ruby may not use the terms messages or receiver as to not confuse the reader. However, to truly appreciate Ruby and eventually master the language you'll need to think in terms of objects and messages. The receiver is to the left of the period ( . ) while the message being sent is to the right of the period. If no receiver is specified then self is the default receiver. Ruby-docs uses the example,