So far, we’ve seen examples in which our code looks very similar to PHP. As I mentioned before, I purposely did this to showcase the flexibility of Ruby. This makes the change to Ruby easier than other languages in which the syntax is a lot different than Ruby. However, this is only the beginning of our journey to becoming a Ruby developer. If we want to be able to read and write Ruby code and snippets like seasoned Ruby developers, we will need to see how the community has come to make Ruby code. In short, while we can write our code similar to other languages, we should avoid this practice and, in the process, learn about what Ruby has to offer to make our code more and more readable.
The first step we are going to take toward this goal is to remove unnecessary syntax within our code. To do this, we also must understand the utility of what we are removing.
Let’s take for an example our original code:
name = "bernard";
age = 40;
height_in_cms = 177.5;
chocolate_allergy = true;
travel_bucket_list = ["Turkey", "Japan", "Canada"];
In Ruby, the semicolon can be useful to separate multiline code into a single line dividing each line with a semicolon. If we took the name and the example to turn it into uppercase, we would have the following:
name = "bernard"; name.upcase!(); puts(name);
And this works perfectly fine. But remember, we are trying to make our code more readable. This is not more readable. It’s the opposite. And, if we are not going to write our whole code in a single line, then let’s take the original snippet (in multiple lines), and remove every single semicolon. This is starting to look more like Ruby:
name = "bernard"
age = 40
height_in_cms = 177.5
chocolate_allergy = true
travel_bucket_list = ["Turkey", "Japan", "Canada"]
This certainly seems to improve readability slightly by removing unused characters, but we are not finished. Let’s put this into practice with another example. Let’s write an example that will print out the string This person is allergic to chocolate
if the value of the $chocolate_allergy
variable is set to true
. Because of our background in PHP, we might be compelled to write something similar to PHP. In PHP, we would write the following:
$chocolate_allergy = true;
if($chocolate_ allergy)
{
echo "This person is allergic to chocolate";
}
With this in mind, we would write the following in Ruby:
chocolate_allergy = true
if(chocolate_allergy)
puts("This person is allergic to chocolate")
end
This works fine, but it still looks a lot like PHP. An intermediate Ruby developer would most likely write something like this:
chocolate_allergy = true
puts "This person is allergic to chocolate"
if chocolate_allergy
This is getting more and more readable by the second. But it also brings a couple of new practices to the table. For starters, the puts
sentence is not surrounded by parenthesis. This is because, in Ruby, the use of parenthesis is optional for functions and methods. This is extremely useful as it’s starting to read like plain English. It works with functions with multiple arguments, too. As an example, an implemented function could very well look like this:
add_locations "location 1", "location 2"
Of course, this becomes cumbersome if we need to call nested functions. Let’s take this example with two functions:
def concatenate( text1, text2 )
puts text1 + " " + text2
end
def to_upper( text )
return text.upcase()
end
The concatenate
function takes two strings and prints out both strings joined with a space between them. The second function just turns the input string into an uppercase string and returns the value. And this is where it could become problematic if we failed to use the parenthesis. If we wanted to concatenate the two strings and turn each string into an uppercase string, we could try the following:
concatenate to_upper "something", to_upper "else"
But we would fail miserably because the Ruby interpreter doesn’t know that "something"
is the argument for the to_upper
function. We can easily fix this with parenthesis:
concatenate to_upper("something"), to_upper("else")
Be careful with this knowledge as, like everything else, if overdone, it can be detrimental to our code’s readability. There are two additional points that we need to consider while deciding whether to use parenthesis. The first is that these rules also apply to the definition of the function. So, the concatenate
function can be defined like this:
def concatenate text1, text2
puts text1 + " " + text2
end
The second point is that the rule also applies to functions with no arguments – that is, we may remove the parenthesis from them, too. Let’s take the following as an example:
return text.upcase()
This will now become the following:
return text.upcase
More importantly, the use of methods that use the question mark and destructive methods (!
) now make perfect sense for readability.
Let’s look at the following:
name.empty?()
This becomes as follows:
name.empty?
As another example, let’s take the following:
name.upcase!()
This now becomes as follows:
name.upcase!
The last point we will look at now is related to how Ruby behaves with the return of values. While a method can explicitly return a value with the return
keyword, Ruby doesn’t need this keyword. Within functions and methods, Ruby automatically returns the last value that is referenced. Let’s use the following example for this:
def to_upper text
return text.upcase
end
That example would turn into this:
def to_upper text
text.upcase
end
You will see a lot of Ruby code like this. It can be intimidating and confusing at first, but once you understand what Ruby is doing, it simply starts to make more sense.
As you have probably realized by now, Ruby’s creator put a lot of emphasis on these tools to make it easier to write readable code. The community adopted this ideology and put it into practice. We not only see code using these conventions and rules to increment readability but we also see Ruby programmers adopt other conventions that, while they are not part of the Ruby rules per se, make perfect sense when used in context. I’m referring to variable and method naming. Because Ruby developers will try to make their code read like plain English, they will spend a lot of time thinking about how to name methods and variables to make the code more readable. For this reason, snake-case is more often used in Ruby, as it helps with readability. With that in mind, let’s look at this example:
chocolate_allergy = true
puts "This person is allergic to chocolate"
if chocolate_allergy
We can still improve its readability. And it wouldn’t just be a syntactic change; it would also involve variable names and even defining a method, just to improve readability. So, a seasoned Ruby developer might write the final snippet for this example as follows:
def say text
text
end
is_allergic = true
say "This person is allergic to chocolate" if is_allergic
As you can see, Ruby developers will go very far to make the code as readable as plain English. Of course, this is not always feasible and sometimes it’s not practical as it at times requires putting a lot of effort into writing even something simple, but for the most part, as long as it’s readable, by following these guidelines, other developers will thank you, not just the Ruby ones.