00:00:10.340
Good afternoon, my name is Claudio, and I'm really excited to be here at RubyConf.
00:00:17.490
This talk is actually about Ruby, the programming language that we all love to write and read. It's a language that is a little old, but still evolving.
00:00:30.060
In fact, there is a new release every year with new methods added. Today, I will provide an overview of some methods that I'm going to cover during this talk.
00:00:44.010
Some of these methods have been in Ruby for many years, while others were just introduced in the 2.4 release last December.
00:01:02.219
The format I chose for this talk is a refactoring journey, and I invite you all to join me on this journey.
00:01:12.869
We will take a problem—an actual problem I faced at a previous job—and find a solution in Ruby. We'll begin with the first pass and then iterate through the problem, utilizing some of these methods to improve our code.
00:01:21.479
Whether you are a beginner or an expert Ruby developer, I hope you will learn something from this talk.
00:01:38.579
Now that the doors have magically closed, let's get started. Let me give you some context for the example problem we will use to explore these methods.
00:01:52.350
This example revolves around YouTube URLs, which I dealt with frequently at my previous job. If you have ever watched a video on YouTube, you've likely encountered a URL of one of these types.
00:02:06.450
For instance, the first URL is for a YouTube video, the second URL is a shorter format for another YouTube video, the third and fourth URLs are for YouTube channels, and the last URL is for a YouTube playlist.
00:02:26.140
So we have different URLs that are subtly different strings representing distinct types of resources.
00:02:33.730
We are going to write a method called 'parse' which accepts a string as input and identifies the type of YouTube resource it represents.
00:02:46.420
For the first type, which is a YouTube video, ideally this 'parse' method should return that it is a video. In the second case, we expect it to return a channel based on the name of that channel.
00:03:06.310
For instances where the URL does not match a YouTube resource, we expect it to return 'unknown'. As Rubyists, we want to write code that is not only correct and complete but also clear and compact.
00:03:20.109
We aim to follow the philosophy of 'Don't repeat yourself.' This is the problem we will address over the next thirty minutes.
00:03:25.480
Before diving in, I want to give you a moment to think. If this were a job interview and you were presented with this problem, what methods would you use if you had access to all the methods in the Ruby standard library?
00:04:02.889
Okay, let's start with a first attempt. I noticed that these URLs start in different ways: the first one starts with 'youtube.com/watch', indicating a video; the second starts with 'youtube.com/', suggesting it's a channel. The last one doesn't even contain 'YouTube,' so it may be classified as unknown.
00:04:27.550
My first thought is to use the 'start_with?' method from the String class. This method returns true if the string starts with one of the specified prefixes. For example, 'hello'.start_with?('hell') is true, and 'hello'.start_with?('heaven') is also true because one of the prefixes matches.
00:05:00.010
However, there are some complications. Initially, I believe this first pass will be clear, but there are significant issues.
00:05:06.610
This code isn't compact because we have repetition and fails to deliver correctness. For instance, if the URL is just 'youtube.com/', that is actually the homepage, not a channel.
00:05:43.310
YouTube has strict rules regarding how URLs are formed; every video has a unique 11-character ID consisting of letters, digits, underscores, or hyphens. You will learn this principle today as we delve deeper.
00:06:19.450
To enhance our iteration on the solution, we can employ the new 'String#match?' method added in Ruby 2.4. This method allows us to compare a string with a regular expression to check for a match.
00:06:48.740
Earlier, we needed explicit matching conditions. Using this new approach, we can rewrite our code so that it checks if the given string matches our expected regular expression.
00:07:31.790
In the first case, we can capture the video ID, ensuring we correctly identify it. For a channel, we can require at least one character. This means our URL parser can now distinguish between videos, channels, or unknown types.
00:08:14.870
But we could further improve this code by eliminating the duplicate calls to 'match?' in the next iteration.
00:08:51.500
We can use the triple-equal operator, which allows comparisons with the Ruby language's case statements, enabling us to streamline our checks without rewriting the same checks multiple times.
00:09:25.960
So refactoring allows us to remove code duplication, but our current version still hasn't resolved the initial requirement to return both the Type and any additional desired value, such as the ID or name.
00:09:49.340
Thus, we are searching for a robust way to retrieve those relevant strings when we perform a match.
00:10:34.850
When matching in Ruby we can capture segments using parentheses while assigning them names. This will maximize our ability to extract whatever we need from the last match.
00:10:59.640
For example, when capturing currency values in a string, we can later refer to those named segments to get specific numeric values.
00:11:29.090
So let's write our code capturing IDs for video URLs and channel names to return in the output hash.
00:11:59.350
Even though we've arrived at a solution that works, it still simply returns results without condensing the logic, leading us to redundancy.
00:12:24.360
In Ruby 2.4, there's a concise way to retrieve values from several named groups at once known as 'named_captures'. By applying it to our earlier example, we can get more reusable and elegant syntax by grouping patterns based on functionality.
00:13:03.440
This would further minimize the repetition we currently face in returning grouped types together. Let's see how we apply named captures for our existing environment.
00:13:44.030
With our current example, matching 'youtube.com/whatever' URL works and returns effectively because we can now dynamically capture ID or channel information.
00:14:26.320
Yet even after simplifying this structure, we need to consider the relationship between patterns and proper structures to help manage complexity in what we write.
00:15:09.860
Diving into refactoring again, it's essential we can align keys with each specific group. Rather than leaving them stuck together, the patterns need to be separated for enhanced read-ability.
00:15:53.510
When segregating URL patterns, it's necessary to assign separate constants for each distinct type we will encounter, such as video and channel patterns.
00:16:32.350
By adopting this structure, we lessen the confusion during maintenance or changes to those identifiers later.
00:17:14.090
Next, incorporating Enumarable enables a more powerful response in organizing our operations with patterns in the search for matches.
00:17:55.790
The foundational method of 'find' enables an easy identification of any matching criteria as we raise and understand the limits of iterations during these functional methods.
00:18:40.620
Thus far, the latest method I will implement allows for returning matches through a match method loop capturing only once and iterating until we find what was requested.
00:19:30.350
This approach supplies us with the necessary context around how rare it can be to clarify patterns expected--obviously relying on the knowledge of shape and form when creating them.
00:20:20.940
This newfound methodology continuously demonstrates helping us connect with returning actionable results based on named captures.
00:21:00.370
Placing those results into a hash clears our cluttered earlier structure while refining explicit connections between patterns.
00:21:41.790
I propose developing this more compact way sooner than later to make our future nomenclature a global mapping of data rather than funneling through repetitive checks.
00:22:23.010
As we take everything together, the ability to maintain organizational structure goes both deeply in code read-ability and efficiently back to defining individual parts.
00:23:05.350
Not only does this foster interaction with each recognized pattern, but improving strategy also dictates clarity and direct flow without convoluted segments.
00:23:47.310
Restructuring any future developments can lean more prominently in nested patterns, ensuring the utilization is more accurate than ambiguous.
00:24:30.800
Therefore, wrapping up, I invite feedback or shared ideas correlating to these strategies and suggest a conversational platform beyond today's conference.
00:25:15.800
There are several methods residing with Ruby's library to flourish your coding journey; it's essential to utilize these effectively for your benefit.
00:25:56.650
Thank you for your attention, and I'm eager to answer questions or continue our conversation throughout the conference!