14
.
11
.
2023
1
.
09
.
2019
Ruby on Rails
Ruby

Ruby Quirks

Jan Matusz
Ruby Developer

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...

https://gist.github.com/Marahin/6c3f445343dfdedf723bbd7b853bc9f4#file-obf-rb

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.

If by any chance you're planning to visit DLD Conference in Tel Aviv do not hesitate to visit us, we can talk a bit more about our company!

Jan Matusz
Ruby Developer

Check my Twitter

Check my Linkedin

Did you like it? 

Sign up To VIsuality newsletter

READ ALSO

How to become a Ruby Certified Programmer Title image

How to become a Ruby Certified Programmer

14
.
11
.
2023
Michał Łęcicki
Ruby
Visuality
Vector Search in Ruby - Paweł Strzałkowski

Vector Search in Ruby

17
.
03
.
2024
Paweł Strzałkowski
ChatGPT
Embeddings
Postgresql
Ruby
Ruby on Rails
LLM Embeddings in Ruby - Paweł Strzałkowski

LLM Embeddings in Ruby

17
.
03
.
2024
Paweł Strzałkowski
Ruby
LLM
Embeddings
ChatGPT
Ollama
Handling Errors in Concurrent Ruby, Michał Łęcicki

Handling Errors in Concurrent Ruby

14
.
11
.
2023
Michał Łęcicki
Ruby
Ruby on Rails
Tutorial
Recap of Friendly.rb 2024 conference

Insights and Inspiration from Friendly.rb: A Ruby Conference Recap

02
.
10
.
2024
Kaja Witek
Conferences
Ruby on Rails

Covering indexes - Postgres Stories

14
.
11
.
2023
Jarosław Kowalewski
Ruby on Rails
Postgresql
Backend
Ula Sołogub - SQL Injection in Ruby on Rails

The Deadly Sins in RoR security - SQL Injection

14
.
11
.
2023
Urszula Sołogub
Backend
Ruby on Rails
Software
Michal - Highlights from Ruby Unconf 2024

Highlights from Ruby Unconf 2024

14
.
11
.
2023
Michał Łęcicki
Conferences
Visuality
Cezary Kłos - Optimizing Cloud Infrastructure by $40 000 Annually

Optimizing Cloud Infrastructure by $40 000 Annually

14
.
11
.
2023
Cezary Kłos
Backend
Ruby on Rails

Smooth Concurrent Updates with Hotwire Stimulus

14
.
11
.
2023
Michał Łęcicki
Hotwire
Ruby on Rails
Software
Tutorial

Freelancers vs Software house

02
.
10
.
2024
Michał Krochecki
Visuality
Business

Table partitioning in Rails, part 2 - Postgres Stories

14
.
11
.
2023
Jarosław Kowalewski
Backend
Postgresql
Ruby on Rails

N+1 in Ruby on Rails

14
.
11
.
2023
Katarzyna Melon-Markowska
Ruby on Rails
Ruby
Backend

Turbo Streams and current user

29
.
11
.
2023
Mateusz Bilski
Hotwire
Ruby on Rails
Backend
Frontend

Showing progress of background jobs with Turbo

14
.
11
.
2023
Michał Łęcicki
Ruby on Rails
Ruby
Hotwire
Frontend
Backend

Table partitioning in Rails, part 1 - Postgres Stories

14
.
11
.
2023
Jarosław Kowalewski
Postgresql
Backend
Ruby on Rails

Table partitioning types - Postgres Stories

14
.
11
.
2023
Jarosław Kowalewski
Postgresql
Backend

Indexing partitioned table - Postgres Stories

14
.
11
.
2023
Jarosław Kowalewski
Backend
Postgresql
SQL Views in Ruby on Rails

SQL views in Ruby on Rails

14
.
11
.
2023
Jan Grela
Backend
Ruby
Ruby on Rails
Postgresql
Design your bathroom in React

Design your bathroom in React

14
.
11
.
2023
Bartosz Bazański
Frontend
React
Lazy Attributes in Ruby - Krzysztof Wawer

Lazy attributes in Ruby

14
.
11
.
2023
Krzysztof Wawer
Ruby
Software

Exporting CSV files using COPY - Postgres Stories

14
.
11
.
2023
Jarosław Kowalewski
Postgresql
Ruby
Ruby on Rails
Michał Łęcicki - From Celluloid to Concurrent Ruby

From Celluloid to Concurrent Ruby: Practical Examples Of Multithreading Calls

14
.
11
.
2023
Michał Łęcicki
Backend
Ruby
Ruby on Rails
Software