RubyConf 2021

Control methods like a pro: A guide to Ruby's awesomeness, a.k.a metaprogramming

Control methods like a pro: A guide to Ruby's awesomeness, a.k.a metaprogramming

by Masafumi Okura

In this talk titled 'Control methods like a pro: A guide to Ruby's awesomeness,' Masafumi Okura explores the advanced features of methods in Ruby, especially focusing on metaprogramming. Okura begins by highlighting the unique aspect of methods in Ruby: they are objects, which allows for dynamic manipulation such as storing them in variables and wrapping them in other objects like Proc.

Key points discussed in the video include:

  • Understanding Methods: Okura emphasizes the need for Ruby programmers to deepen their understanding of methods beyond basic usage. He introduces the idea of having conventions over method invocations, like how testing frameworks detect test methods automatically.
  • Listing Methods: The talk explains Ruby's built-in capabilities to list available methods for objects, using methods like methods, private_methods, and singleton_methods. Okura distinguishes between the return types of these methods, noting that they return method names as symbols, not method objects directly.
  • Method Objects: The concept of method objects in Ruby is elaborated upon. Okura distinguishes between Method and UnboundMethod, explaining how both work and their respective use cases. Method objects can be stored in variables and invoked later, while unbound methods require binding to an object before invocation.
  • Defining and Redefining Methods: The presentation showcases various dynamic methods of defining methods in Ruby, emphasizing the use of define_method for creating methods at runtime. Okura also discusses the processes of undefined and removing methods, illustrating the dynamic nature of Rails application methods.
  • Real-World Application: Throughout the talk, Okura presents a real-world example involving a logic class that collects validation methods, emphasizing how the framework allows for clean logic separation without sacrificing performance. He discusses the tiny hooks library he created, which manages hooks efficiently.
  • Conclusions: The speaker encourages Ruby developers to embrace metaprogramming, summarizing that manipulating methods does not break Ruby but instead enhances its capabilities.

In conclusion, Okura urges the audience to explore methods in Ruby further and to utilize tools like tiny hooks to improve performance and maintainability in their coding practices. The video serves as a comprehensive guide for Ruby developers looking to leverage the power of methods and reevaluate their understanding of language features.

00:00:10.800 Hello everyone, my name is Masafumi. I'd like to talk about methods.
00:00:16.160 The title of my talk is 'Control Methods Like a Pro.' The topic of my talk is methods. In this talk, you'll learn about some unfamiliar aspects of methods in Ruby.
00:00:28.960 You might think that you're already familiar with methods in Ruby as a Ruby programmer because we use them regularly. However, there are many things to uncover.
00:00:41.680 Have you ever wanted to have conventions over method invocations, similar to many tests? For instance, when we execute tests in a certain mode, if a method name starts with 'test,' many testing frameworks can automatically detect it as a test method and execute it. However, if you didn't want to modify existing methods with performance overhead, we commonly use things like ActiveSupport callbacks, which tend to introduce some overhead.
00:01:21.680 So what if we could achieve the functionality of ActiveSupport callbacks without that performance penalty? I'll show you some examples.
00:02:06.000 Take a look at this code. Here we have a Logic class, which is a superclass for an abstract logic flow. It contains only one method, 'call.' In that method, we collect methods whose names start with 'validate.' We then log the method name before calling it, and finally, we call the main logic.
00:02:28.160 In this code, we define two validation methods. One checks for the presence of a name variable, while the second checks the length of the name attribute.
00:03:10.240 The result of calling these methods is interesting. First, we require the concrete logic and assign a proper name to the logic. Upon calling it, we receive the validation method names printed out alongside the provided name. The result appears to be okay, but when we fail to provide a name, it raises an exception, which works as expected.
00:03:34.880 Now, how do we achieve this? That's what I'd like to demonstrate in this talk. By the way, I am Masafumi Okura, and this is a brief introduction of myself: I've been involved in Ruby development since around 2012. I work as a freelance Ruby on Rails developer and am also involved with organizing a tech conference called Kaigi on Rails.
00:04:46.080 I am also the creator of a gem called Albo Gem, which is a JSON serializer. When I wanted to customize it using hooks, I came up with the idea of implementing hooks liberally, which inspired this talk.
00:06:07.199 In part one of this talk, we'll explore methods that list available methods within Ruby. Ruby provides several methods to list the available methods on a given object.
00:06:54.080 When we want to call a method, it typically needs a receiver, which means that a method is tied to an object. Therefore, when we look to list methods on that object, we can leverage various methods available in Ruby.
00:07:23.919 Three methods we'll discuss are: the 'methods' method, which lists public and protected methods; the 'private_methods' method, which lists only private methods; and the 'singleton_methods' method, which can be used to list class methods.
00:08:01.760 Next, we'll talk about methods that fetch specific method objects. The 'method' method returns a method object with a given name from an object, which is quite important.
00:08:23.480 For example, if we take the string object and call 'method' on it with the method name 'gsub,' we can retrieve and store that callable method object for later use. Additionally, Ruby also offers an 'instance_method' method for obtaining details about instance methods.
00:09:26.960 In Ruby, methods are treated as objects. We can interact with method objects to gain insights about them. The Method class contains information about specific method objects, including their parameters and location within the source code.
00:10:46.760 For instance, we can inspect various properties of methods including names, parameters, and their locations, which is particularly useful when debugging code, especially in external gems.
00:12:14.960 Next, I'll show you how we achieve the functionalities demonstrated earlier. First, we have the Logic class and establish the primary logic. This design allows us to concentrate on the core logic instead of the execution order.
00:13:10.000 The key point is that validation methods must start with 'validate_.' Now, let's proceed to defining methods.
00:13:48.960 While defining methods usually involves the 'def' keyword, we can also utilize alternatives like 'define_method.' This method is dynamic and is capable of accepting symbols as method names.
00:14:45.360 In Ruby, methods can be undefined as well. This can be achieved using the 'undef' keyword and the 'remove_method' method, allowing us to redefine or modify methods effectively.
00:15:30.000 Combining this functionality allows us to redefine methods while retaining the original method body. We can achieve this dynamically by leveraging the method objects, fetching the method body, and creating new procs.
00:16:59.680 Regarding the demo, I have a YouTube repository called Tiny Hooks, created with the intention of defining hooks simply and efficiently. This solution outperforms ActiveSupport by a significant margin.
00:18:25.440 To conclude, in Ruby, methods are indeed objects. Engaging with them is not something to be feared; it empowers us to harness metaprogramming capabilities to create compelling solutions.
00:18:54.720 I encourage you to explore the resources available for Tiny Hooks and consider contributing. Thank you!