Ruby Quirks

Jasiek Matusz
Visualitypl
Published in
5 min readSep 4, 2019

Ruby is a beautiful language to work with. It provides tons of amenities for developers.

Like every other language, though, Ruby has things that you may not be aware of, or may not fully understand — and these quirks are the subject of today's blog post.

? character literal notation

It is a simple notation that allows to create a string out of a character (in Ruby > 2):

docs.ruby-lang.org does not provide too many details about it:

There is also a character literal notation to represent single character strings, which syntax is a question mark (?) followed by a single character or escape sequence that corresponds to a single codepoint in the script encoding.

A person named Josh Cheek commented about this in the rubyguides.com article:

Also, their existence is historical rather than practical, back when chars were still int literals (1.8, IIRC), it was useful to have a syntax for going from the char to the ordinal, which is what this was for. Then when chars became single-letter strings, they made the syntax resolve to that rather than deprecating it and breaking lots of code.

__END__ & DATA

These keywords hold a very specific functionality, that is not often used — at least in the web development specter of Ruby use cases. Probably it can be used in scripting / CLI tools.

__END__ specifies… well, the end of a Ruby program

When executing this keyword, nothing past it will be interpreted. Consider this code:

And then we run it:

DATA

DATA allows you to get access to whatever is past __END__. If we slightly modify the code above:

And then execute it:

This gist also should give you an idea of how you can use it.

::method

Usually, when you see code samples in Ruby all methods are invoked with a . — such as 12.to_s, “1”.to_i, User.create! etc.

Having said that, it is perfectly valid to call these methods using :::

It is not considered as a good practice — the recommended way is obviously to call methods through a . operator.

However, if you want code obfuscation, you can go crazy using ::. For instance, adding two integers in Ruby is nothing else than calling a #+ method on one of these, and then passing the other one as an argument:

This means…

Looking crazy, isn’t it

Shovel method on strings — <<

Shovel method can be used on instances of String class. It can be provided with both an integer representation of the character (ASCII code) and another string:

redo and retry

These methods are similar in their functionality. redo allows you to, well, re-do the current iteration block, where retry repeats whole block.

Consider this code:

It does a couple of things:

  1. Defines theretry_on_raise function that accepts a block.
  2. Then, if the block raises any exceptions, it is going to retry the block once.
  3. Exactly 3 times it executes retry_on_raise.
  4. It randomly passes raise into the block so the method would have a chance to retry.
  5. Also it redos the iteration if the upcoming index is 2.

Whether you should use these two — it is hard to say. retry is something I have seen multiple times in Rails applications. I think that when you have a good reason to use it, it is fine — but then redo makes it a bit more complex.
The developer would have to mind that it is no longer the whole block being called again, but a single iteration step.

In other words — I think it really depends on the case.

Ruby Quicktips also has quite a few good examples worth checking out.

Literals

Numbers

Binary 1111is 15decimal. Ruby supports specifying values in different number systems by passing a proper prefix:

d or D stands for decimal, x or X for hexadecimal, 0 or 0o stands for octal, binary b. The alphabetic part of the prefix is case insensitive, hence it can but does not have to be capitalized.

Another interesting part in number literals is the underscore separator. The documentation does not specify any explicit usage for it, except for human readability improvements.

It is super nice to use it when you deal with constants that specify a big number. It makes it harder to do human errors such as missing a single 0 in a big number.

Ranges

You must have used some kind of range at a given point while working with Ruby. Maybe using rand(1..10) or an iteration of some kind.

But do you know the difference between ... and .. range? Its pretty simple: 1..10 is an inclusive range (starts from 1, ends at 10), and 1...10 is an end-exclusive range (ends at 9).

Symbols

While it may be common knowledge for most of you, I have experienced that some people do not realize you can actually put string interpolation into symbols.

In the wrong hands, it may be a terrible idea, since symbols are not garbage collected — but sometimes it is really useful.

Ruby has pretty good documentation for literals, so if you are interested in seeing more, head over to docs.ruby-lang.org!

Proc & .[]()

In CultureHQ’s Weird Ruby I had stomped upon something that I did not know myself.

Usually when handling Procs, I just called them by .call method — seems verbose, explicit and understandable to any developer that might come after me.

Yet it seems that you can also call Proc by square brackets method ([something]).

It made me think so I dug into Class: Proc documentation, and found out there are several ways to call a Proc instance:

In general, it is a good practice to write code that can be understood by others — be it your team members or developers that may take over the project eventually. Hence I would say that .call or .yield would be the way to go here, as personally I would have had no idea on what [“Thomas”, 23] really does.

I think that there is a good chance I am not the only one and .call would make it way more explicit.

I hope this article has raised at least a couple of eyebrows.
Ruby is an awesome tool — but like any other, it has its weird moments.
Feel free to share your thoughts in the comments section!

If you’re interested in more blog posts like this please visit our Visuality Blog or our Medium Page.

--

--