00:00:12.719
Hello everyone, my talk today is titled 'Reading RSpec — A Journey of Metaprogramming.' This presentation will primarily focus on RSpec, partly because there was a significant amount of interest in RSpec on the Euruko website.
00:00:20.720
I wanted to discuss RSpec because I use it every day, and it's truly an awesome tool. However, I didn't realize that yesterday we had a keynote speech from the original author of RSpec. This is a rather bizarre experience for me, talking about some code in front of its original creator.
00:00:38.719
This is my first experience doing so. Additionally, my talk today will cover DSL, or Domain Specific Language, which is a popular topic. We have another talk tomorrow from Tom about DSL, so I expect we will learn a lot about it.
00:00:57.840
Domain Specific Language is intended to be readable, especially like English. In RSpec, we describe it using 'it' and 'expect.' However, what exactly do these expressions do? Although they appear to be written in English, they are, in fact, Ruby code that is executable. To fully understand them, we need to engage in code reading.
00:01:24.439
Thus, this talk is centered on code reading. There are many takeaways to be had from this discussion. The first takeaway is that reading code is enjoyable; it's one of my hobbies. In fact, I've organized a meetup specifically for reading code.
00:01:55.880
In that meetup, we have read some notable gems, such as FactoryBot and Webrat. For the Webrat meetup, we even invited its original author, Takahashi-san, known for the Takahashi method, who explained the intricacies of Webrat, making it a fascinating session.
00:02:18.519
This talk is going to be rushed because I only have 40 minutes, so please bear with me. By the way, let me introduce myself. My name is Masafumi; you can call me Masa.
00:02:46.760
I work as a freelance web developer in Japan. I've been involved in organizing meetups and communities, including Ruby jams and code reading groups. Additionally, I run a domestic conference that started three years ago, and this year marks its first in-person format.
00:03:14.879
I'm the chief organizer of this conference, which I founded. Moreover, I have developed Alba, a Ruby gem that functions as a JSON serializer, akin to ActiveModel::Serializer, but it is much faster and results in shorter code. I actively maintain it.
00:03:41.640
I read source code using Vim, where I have been a loyal user for about ten years. I also planned to create new documentation, as I mentioned in the pitch for my UNC conference talk; unfortunately, that talk was not accepted. I'm a coffee lover as well, so if you have any recommendations or advice for this area, it would be greatly appreciated.
00:04:19.639
This is my first time at this conference, and I didn't reserve any hotels yet, so I am still gathering information on that.
00:04:36.520
Now, an important note: This talk is about metaprogramming. But what exactly is metaprogramming? Simply put, it is programming that writes programs.
00:04:49.199
That is the simplest explanation I can provide. The second takeaway is that metaprogramming is fundamentally just programming. It may be harder to read than normal code, but it remains readable. I aim to prove that in this talk.
00:05:23.160
You will learn a lot today, and don’t worry, we will wrap everything up at the end of the talk. Additionally, as you might know, in Ruby, everything is an object. This includes classes, modules, and even methods.
00:05:56.880
I will demonstrate how RSpec utilizes this functionality. Let's get started.
00:06:21.599
Let’s begin with an example of a simple RSpec file. Here we typically use 'describe' and 'let.' The 'let' variable is here; everything seems normal.
00:06:39.920
In this talk, I won’t discuss 'expect' because it’s technically implemented in a separate gem, making it cumbersome to shift back and forth between different gems and directories.
00:07:12.800
What I will focus on is the 'describe' and 'let' keywords. What does RSpec do with 'describe'? This raises our first question: What exactly does 'describe' do?
00:07:37.440
Imagine you want to learn what's happening inside a method; take a moment to think about it. There are several options available, but my favorite is to ask Ruby.
00:07:57.919
Ruby knows almost everything or, at least, much about our code. We can call the 'method' method on RSpec and fetch the argument 'describe' along with its source location.
00:08:19.440
This approach reveals the line number where 'describe' is defined, including the file location. This demonstrates that the 'method' method can be used to find the source location of any method.
00:08:56.520
The class being defined here calls for the class of the RSpec itself. Like every class, RSpec has its own class called the Singleton class. Within this class, it defines new class methods.
00:10:03.520
The method we're looking at is an alias for exposed example group. When the 'describe' method is executed, it sets up the context for our tests.
00:10:33.440
In this example, the string or symbol we provide as an argument indicates the nature of the tests. The 'example group' class should respond to the 'describe' method.
00:11:06.039
Let's investigate the example group class to find how it works. This method exposes the example group alias method, which should be invoked somewhere within the code.
00:11:40.440
Searching for its occurrences yields several results, but many belong to the same file, dsl.rb. The correct line of execution reveals the 'define example group method,' which you'll see reflects this functionality.
00:12:08.120
In Ruby, defining methods of methods is a unique concept, such as the ability to define multiple methods simultaneously.
00:12:35.760
Moving forward, we can delve into the 'let' functionality, a method definition that also creates methods, similar to the 'describe' method.
00:13:02.079
This 'let' method, like 'describe,' is a method intended to define other methods but with powerful behaviors. It exhibits lazy evaluation, storing results to be fetched later without re-evaluating.
00:13:35.679
As we continue understanding RSpec's mechanisms, pay attention to how class names alter with different contexts. The generation of classes happens dynamically with the arguments passed to 'describe.'
00:14:10.480
This new class can inherit from another, further demonstrating how RSpec utilizes Ruby’s features to allow complex but organized test structures.
00:14:42.799
When creating subclasses or self-references in RSpec, knowing when the context shifts is critical. The 'modu exact' method will be invoked, altering the self-parameter for block execution.
00:15:14.440
This block will execute under the altered context as defined through the methods we've discussed.
00:15:52.579
The essence of meta programming in Ruby requires familiarity with such constructs, as they will show up frequently within RSpec code.
00:16:15.859
From our previous examples, we have seen how self can change in RSpec during its processing, providing important clues toward its underlying design.
00:16:54.560
Another critical takeaway is that in Ruby, almost everything is a method, making understanding how methods are invoked and defined crucial to mastering Ruby.
00:17:27.680
As we explore through the code of methods like 'let,' remember that this is simply a method to define additional methods on-the-fly.
00:18:12.200
Let's analyze what takes place within defined methods. In these definitions, you'll notice patterns that emerge, showing lazy retrieval of previously defined methods.
00:18:52.840
This laziness is key; it saves processing time as you can access results that have already been computed when the block is first executed.
00:19:36.440
Returning to our overview of obtaining the definitions of methods, reading comments within the library can be incredibly helpful.
00:20:02.400
There’s an entire module that contains the definitions of 'let,' demonstrating Ruby's ability to dynamically include and include methods efficiently.
00:20:45.800
We may not fully grasp every detail immediately, but with comments and structured reading, the intent of each code section starts to become clearer.
00:21:31.360
Finally, let’s link everything back to how we invoke these class methods and understand the types of objects being created.
00:22:15.680
This facilitates the setup of examples within our tests, and as each class defines itself, it sets up its container with example instances.
00:23:05.000
Ultimately, understanding RSpec boils down to following these deeply nested calls, keeping a keen eye on how each context modifies itself and defines methods.
00:23:59.760
The takeaway here is that great Ruby developers like you should be practiced in reading and executing complex examples—each adding to a more significant body of work within our understandings.
00:24:41.760
I want to reiterate that the essence of RSpec is about automatically handling instances and grouping tests effectively, making it a vital tool in any Ruby developer's toolkit.
00:25:33.680
As I conclude this talk, I hope you’ll take many insights away. Remember to always read comments diligently, grasp the context of your objects, and embrace metaprogramming in your Ruby development.