Help more people learn by sharing this post!

All posts by Jesus Castello

Understanding Mutable Objects & Frozen Strings

Let’s talk about mutability.

What does it mean for an object to be mutable? Don’t let the fancy word deceive you, it just means that the object state can be changed.

Not all objects in Ruby are mutable, for example, it doesn’t make any sense for numbers or symbols, or even true or false (which are also objects) to change.

But other objects, especially those that are meant to store data, like Array or Hash objects, make a lot more sense because it would not be very efficient otherwise.

The alternative to mutating an object, but still being able to get an updated version of the object, is to make a new copy of the object with the changes and then return this new object, leaving the original object intact.

If arrays were immutable and you wanted to change just one element of an array, you would have to copy all the data, including the elements that didn’t change.

Imagine having to copy a one million (or more) element array every time you had to make any change, doesn’t matter how small! That wouldn’t be very efficient, would it?

Mutability & Variables as Pointers

There is a category of programming errors which are caused by the combination of two things: mutable objects & the fact that variables don’t contain data directly, but a reference to where this data is stored.

One way these errors show themselves is when you try to ‘alias’ a variable.

Here is an example:

In this example, both name and other_name contain a reference to the same string object. You can use either to display or modify the contents of this string.

ruby freeze

The problem appears if we treat other_name like a copy of the string.

Since both variables point to the same string, we just changed “Peter” to “Teter”. That’s a problem because we probably meant to keep “Peter” around.

5 Tips to Become a Better Ruby Developer (must read!)

Cloning Objects

One way to deal with this issue is to use the dup method, that will tell Ruby to give us a copy of the object. There is also a clone method, which in addition to giving you a copy of the object, it copies the frozen status & any singleton methods defined on the object.

Let’s see an example:

In this example, you can see how the original numbers array remained unchanged. Try removing that dup call on the third line and see what happens :)

The Freeze Method

Another way to keep an object safe from unwanted changes it to ‘freeze’ it. Any Ruby object can be frozen by using the freeze method.

When an object is frozen, any attempt to change this object will result in a RuntimeError exception.

Note: You can use the frozen? method to check if an object is frozen or not.

Example:

One thing to keep in mind is that this will only freeze one object, in this example the array itself, which prevents us from adding or taking away items from it. But the strings inside the array are not frozen, so they can still be changed!

If you want to freeze the strings you need to call freeze on them. Like this: animals.each(&:freeze).

Frozen Strings

Mutable objects also have an impact on performance, especially strings. The reason is that there is a good chance that in a large program the same string is used multiple times.

Ruby will create a new object for every string, even if two strings look the same, or in other words, they have the same ‘content’. You can easily see this happen in irb if you use the object_id method.

Here is an example:

This is a problem because these objects are consuming extra memory and extra CPU cycles.

Starting with Ruby 2.1, when you use frozen strings, Ruby will use the same string object. This avoids having to create new copies of the same string. Which results in some memory savings and a small performance boost.

Rails makes extensive use of frozen strings for this reason. For example, take a look at this PR.

This prompted the Ruby development team to start considering moving strings into immutable objects by default. In fact, Ruby 2.3, which was just released a few days ago, includes two ways to enable this for your project.

One is to include # frozen_string_literal: true at the top of every file where you want strings to be immutable. And the other is to use a command-line argument --enable=frozen-string-literal.

Immutable strings by default will probably land in Ruby 3.0.

Now don’t go crazy and start freezing all your strings in your app. You only want to do this for strings that are used hundreds of times to see some sort of benefit. Having said that, here is a tool that you can use to find potential strings to freeze.

Know Your Methods

Not all the methods in a mutable object will actually change the object, for example, the gsub method will return a new string, leaving the original untouched.

Some of these methods have an alternative version which does change the original object in-place, which is often more efficient. These methods often end with an exclamation symbol ! to indicate their effect.

Two examples of these ‘bang’ methods are gsub! and map!.

Also, note that a method ending in ! doesn’t always mean that it’s a ‘method that changes an object’, in more general terms, the ! symbol is used to denote ‘danger’. One example of this is the exit! method, which will exit the program immediately, ignoring any exit handlers.

There is also methods that change the object and don’t end with a ! symbol. For example: delete, clear, push, concat, and many more.

Wrapping Up

Mutability can be a tricky subject, but since you read this post you are now much better prepared to deal with it. Don’t hesitate to consult the Ruby documentation if you aren’t sure what a method is doing, this will help you avoid issues.

I hope you found this article informative, please share it with your friends so they can enjoy it too. Also join my email list below so you don’t miss more content like this when it comes out!

Ruby Time & Date Classes

If you want to do anything related with time you probably want to use some sort of class that can store and work with this type of data. In this article you will learn what time-related classes and methods are available in Ruby and how to use them.

The Time Class

To manage time in Ruby you can use the Time class. This class can represent a date (day/month/year) and a time (hours/minutes/seconds). This is stored by the Time class as the number of seconds since the Epoch, also known as Unix time.

There are a few ways to initialize a Time object. You can get an object that represents the current time using Time.new or Time.now.

You can also create a Time object using an Unix timestamp and the at method.

You can ask a time object for any of its components. For example, you can ask what day and month a time object is representing.

In addition, you can also ask if this date corresponds to a certain day of the week. For example: “Is this date a Sunday?”. These are predicate methods, meaning that they will return either true or false.

Time Zones

A Time object also has a time zone associated with it, you can check the current time zone for a Time object using the zone method. This will give you the time zone abbreviation.

If you want the time zone offset you can use the utc_offset method. The output for this method is in seconds, but you can divide by 3600 to get it in hours.

Example:

Ruby Time Formatting

The default string representation for the time & date given to you by the Ruby Time class might not be what you want. Fortunately, there is a method you can use to get almost any format you need. This method is strftime, which basically means ‘format time’.

The way it works is by passing in a string with format specifiers, these specifiers will be replaced by a value from the time object. If you have ever used the printf method the idea is very similar to that.

Let’s see some examples:

As you can see, this method is very flexible. You can find more info on the different formats available on the following links:

Time Difference (Addition & Subtraction)

Sometimes you don’t want the current time, but a time in the future or the past. You can do addition with time objects. Remember that the internal representation for Time is in seconds, so you can do this:

In this example you get a time object that is set 10 seconds from the current time. Then you can check if that time has passed yet.

The Date Class

The Date class has no concept of minutes, seconds or hours. This class stores everything internally in terms of days. To use the Date class you need to require 'date'.

You can get the current date using Date.today. Unlike time, Date.new is not an alias for today, so keep that in mind.

Date arithmetic is similar to the Time class, the difference is that you add days instead of seconds.

Date Parsing

The Date.parse method will try to parse anything that looks like a date. It uses a simple heuristic algorithm that tries to detect the input format. Sometimes this will give unwanted results.

Examples:

If you need something more strict you can use the Date.iso8601 method. An iso8601 date has the following format: year-month-day. An ArgumentError exception will be raised on invalid input.

You can use the Date.strptime method and a set of format specifiers to provide your own custom input format. These are the same specifiers that you can use for strftime.

Example:

The Time class can also parse strings to turn then into Time objects. You will need to require 'time' to enable this functionality.

Date Constants

The Date class has some constants that you may find useful. For example, there is an array with the months of the year and another with the days of the week. Months start at index 1 so you can get a direct month number -> month name mapping.

The days start with Sunday, but you can use the rotate method to have the week start on Monday.

The DateTime Class

The DateTime class is a subclass of Date and it can store seconds in addition to dates. Both Time and DateTime can get the same job done, with the main difference being that Time is implemented in C, so it will be faster.

ActiveSupport – Time & Date Methods

If you have used rails you are probably familiar with things like 3.days.ago. These methods are not available in pure Ruby, they are added by the ActiveSupport component of Rails.

Here you can find some examples, notice how these methods don’t return Time or Date objects, but a custom ActiveSupport class.

The code for these methods is actually pretty simple, you should take a look. The source code for TimeWithZone is also worth taking a look at.

Introduction to Refactoring

If you aren’t familiar with the term, refactoring is the act of improving the quality of code without changing what it does. This will make your code a lot easier to work with. In this post you will learn some common refactoring techniques, let’s get started!

Extract Method

One of the most common refactorings is the one known as ‘extract method’. In this refactoring you move some code from an old method into a new method. This will allow you to have smaller methods with descriptive names.

Let’s take a look at an example:

We can start by extracting the ugliest part of this method, the current date generation.

This already reads better, but we can go a bit further. Let’s extract a few more methods to end up with this code:

Yes, the code is longer now, but isn’t this easier to read? Don’t be afraid of small methods, they are good for your code.

Refactoring Conditionals

You can also refactor complicated conditionals into methods to make them more readable.

Example:

The second part of this if statement is not super-readable, so let’s extract it into a method:

What we have done here is to give our condition a descriptive name, which makes things a lot easier for future readers of this code (including you!).

Replace Method with Method Object

Sometimes you have a big method that got out of control. In this case it might be hard to refactor because big methods tend to have many local variables. One solution is to use the ‘Method Object’ refactoring.

“Big methods are where classes go to hide.” – Uncle Bob

Let’s see an example:

To perform the refactoring we can create a new class and promote the local variables into instance variables. This will allow us to further refactor this code without having to worry about passing data around.

Hey! Want to improve your Ruby skills in a big way? Check out my New Ruby Course :)

This is the MailSender class after the refactoring:

And this is the new class we introduced:

Conclusion

Using these refactoring techniques will help you adhere to the Single Responsibility Principle and keep your classes and methods under control.

If you enjoyed this article please share it with your friends so they can enjoy it too :)

ruby case switch

The Many Uses Of Ruby Case Statements

Whenever you need to use some if / elsif statements you could consider using a Ruby case statement instead. In this post, you will learn a few different use cases and how it all really works under the hood.

ruby case

Note: In other programming languages this is known as a switch statement.

Ruby Case & Ranges

The case statement is more flexible than it might appear at first sight. Let’s see an example where we want to print some message depending on what range a value falls in.

I think this code is pretty elegant compared to what the if / elsif version would look like.

Ruby Case & Regex

You can also use regular expressions as your when condition. In the following example we have a serial_code with an initial letter that tells us how risky this product is to consume.

When Not to Use Ruby Case

When you have a simple 1:1 mapping, you might be tempted to do something like this.

In my opinion it would be better to do this instead:

The hash solution is more efficient and easier to work with. Don’t you think?

How case works: the === method

You may be wondering how case works under the hood. If we go back to our first example, this is what is happening:

As you can see, the condition is reversed because Ruby calls === on the object on the left. The === is just a method that can be implemented by any class. In this case, Range implements this method by returning true only if the value is found inside the range.

This is how === is implemented in Rubinius (for the Range class):

Source: https://github.com/rubinius/rubinius/blob/master/kernel/common/range.rb#L178

Procs + Case

Another interesting class that implements === is the Proc class.

You can learn more about procs & lambdas in my upcoming course: ‘Ruby Deep Dive’. Click here to get your free lesson now.

In this example I define two procs, one to check for an even number, and another for odd.

This is what is really happening:

Using === on a proc has the same effect as using call.

Conclusion

You have learned how the Ruby case statement works and how flexible it can be, now it’s your turn to start making the best use of it in your own projects. I hope you found this article useful!

Please share this post so more people can learn! :)

working with apis

Working with APIs

APIs are great because they let you interact with other applications, but they can be a bit intimidating if you never used one before.

In this post I will show you how to get started using your favorite APIs with Ruby.

A simple API

To use an API you will need some form of HTTP client. I like RestClient because it’s easy to use.

Example: Random Chuck Norris joke

This code sends an HTTP ‘GET’ request to the server using RestClient.get(url), then it receives a json string as a response which needs to be parsed by JSON.parse(response). The parsed json is just a regular Ruby hash that we can use to get the data we want, in this case the joke.

The documentation for this API is available here.

Understanding API responses

Api responses can be pretty complex, and it can be hard to read the resulting json to find what you need. Fortunately, the json library has the jj method to pretty-print the output.

In the example above you can do this:

And this is what you get:

As you can see the json structure is more clear now. You can even go a bit further than this with the awesome_print gem, which will add some syntax coloring to the output and even better formatting than jj.

Using gems

If you want to use an API from a popular site like Github or Reddit there are gems you can use to make your life a lot easier.

Example: Using the Octokit gem to get the top 10 Ruby projects on github.

The gem’s documentation should have all the possible API calls you can do with it. Also you can use pry’s ls command to help you explore the available options.

Conclusion

APIs are fun! Now open your editor, use some APIs and create something nice :)