I want to share some of Ruby tricks with you that I have collected over the past few years. I hope that I’ll be able to add a few bits of new knowledge to your current Ruby toolkit.
I dare you try to solve these seven challenges without any documentation or irb at first. All code in this blog post is intended to be run using Ruby 2.5.0 or a more recent version.
To warm up, you can try to guess whether this Ruby code is valid or not —
You may think this is one of these mysterious global variables in Ruby, but actually this is something quite different.
If you type this code
in irb it returns
“?” is Ruby literal that was used as a method to get ASCII code for character prior to Ruby 1.9, in the newer version of Ruby this literal converts a character to a string.
This is the quickest way in Ruby to create a one character string, and it can be used for example like this:
The closest example looks like this:
Admittedly, his code doesn’t look very useful. However, immediately-invoked method can be more valuable in other ways.
You might know that method definition returns method name as a symbol, and it means that we can use it like this:
So, basically every method that accepts the method name as an argument can be rewritten as:
For example, in Rails, it can be used to define a helper method in the controller:
It looks a bit unorthodox—but it’s a trick!
2. Continue method execution after the return statement
We tend to think that the return keyword always returns control back to the context of the method call, but actually we can still continue method execution if we want to. Here’s how: "ensure"block will be called just after "return" statement:
It’s also possible to add a second return keyword to the ensure block and override the returned value:
3. How to return more than one value from the method without explicitly wrapping it into a data structure?
It’s a pretty simple question, but as developers we rarely think of how much of syntactic sugar in Ruby goes unnoticed.
As an example, imagine that you have a method “authorize” that should return a status and some message with it. How would you write this method without wrapping it into an array like this “[status, message]”.
The solution is really easy, you just need to add an explicit “return” and pass multiple arguments to it separated by a comma:
Internally Ruby wraps these values into an array anyway, so for developers it works in the same way if you do this:
4. Create infinitely recursive lambda
Imagine that we want to have lambda that will return the same lambda after every call.
It doesn’t do anything useful (yet), but it’s important to understand how the simplest implementations work in order to do something useful.
5. Infinitely nested Hash!
I guess you already know this Ruby snippet for Hash with default value:
In this example, it returns a new hash for any given key, but it’s only one level deep which is not enough if need data structure with arbitrary deepness.
Hash instance has /#default_proc method that returns block passed to this hash initially which allows us to create hashes recursively.
This pattern can be easily implemented for any data structure and may be useful, for example, to store parsed XML documents or create Tree-like structures.
6. Pass block to a method without explicitly capturing it to a variable
This is my favorite trick in the list and it took me some time to figure out how it actually works. I found it in the source of one popular ruby gem called Faraday. It uses this code to build a connection object for request and passes block to the builder:
As you can see, `Faraday::Connection` expects to receive a block as a parameter for constructor, but the parent method doesn’t contain any reference to the block, and instead it creates `Proc.new` and assigns it to the block variable :|. Here’s how it works.
Creates a new Proc object, bound to the current context. Proc::new may be called without a block only within a method with an attached block, in which case that block is converted to the Proc object.
From Ruby docs: Class: Proc (Ruby 2.5.0)
This means Proc.new implicitly captures the block if it’s given to the method.
But why this code was written this way seven years ago? It would be much easier just to add &block to the method signature and then pass it to the child method. For sure, this advanced technique exists for a reason—and that reason is performance.
Proc creation is considered an expensive operation in Ruby and when you pass &block as a parameter to a method, it always creates a new Proc, even if doesn’t pass the actual block.
So, for the sake of performance, you can check if a block is given, and then capture the block with Proc.new. This definitely decreases the readability of the code, but don’t rush to refactor your code just yet. Ruby 2.5 comes to the rescue and there is no need for this kind of optimization anymore!
You can read more about what changed in Ruby 2.5 here:
And here you can see benchmarks results:
That's all for now, folks!
I hope these tricks were useful for you and now you feel that you know a bit more about Ruby.
Like most professional developers, I usually try to avoid using any tricks in my own code to keep it simple and follow the principle of least surprise. Still, knowing these underlying details always helps to read and understand the code.
What are your favorite tricks and tips in Ruby? Share them in the comments!