Black Bytes
Share this post!

15 Weird Things About Ruby That You Should Know

By Jesus Castello

Ruby is an amazing language with a lot of interesting details that you may not have seen before...

…in this post I compiled some of those details for your own enjoyment in a nice-looking list :)​

1

Heredoc + Method

If you have some data that you want to embed into your program you may want to use a “heredoc”.

Like this:

This will give you a string. But you may want to do some post-processing, like splitting this string into an array of strings.

Ruby lets you do this:

Bonus tip:
Ruby 2.3 introduced the "squiggly heredoc" <<~. This will remove all the extra spaces introduced by indentation, which is a common problem when using heredocs for text.

2

Call a Method Using Double Colon

Apparently this is a thing…

3

Puts with Multiple Arguments

Pretty simple, but could be useful in some situations I guess.

4

Infinite Indexing

Example:

This works because [] is just a method & it keeps returning the first character, which is also a string.

5

De-structuring Block Arguments (or whatever you want to call this)

Want to get rid of some local variables? You will love this trick!

This has the same effect as if we did this:

But it saves you one line of code 🙂

6

Special Global Variables

When you use a regular expression with capture groups it will set the global variable $1 to the first group, $2 for the second group, etc.

The thing about these is that they don't behave like normal variables. They are ‘method-local’ & ‘thread-local’, as described by the documentation.

Also they can’t be directly assigned to like regular global variables.

7

Shovel Method on Strings

There is this “shovel” method on string which doesn’t do what you would expect when you use it with a number

…it’s interpreting the number as an ASCII character.

Here’s another way to do that:

8

Character Literals

Not sure if there are any practical uses for this one…

Let me know in the comments what you think 🙂

9

The RbConfig Module

RbConfig is a module which is not documented & it contains some info about your Ruby installation.

There is some useful info under RbConfig::CONFIG (like compile flags, ruby version & operating system).

10

Spaces, Spaces Everywhere!

You can put as many spaces as you want between a method call & the receiver of that call.

Yes, this is valid Ruby syntax 🙂

11

Infinite Nesting of Constants

You can have an infinite amount of nested constants like this:

The reason this works is that all top-level constants (defined outside any class) are contained in the Object class & every class inherits from Object by default.

Try Object.constants to see what I mean.

12

Chaining the Shovel Operator

You can chain the shovel << operator multiple times:

13

BEGIN & END

Two keywords that you don’t see very often are BEGIN & END. I believe these come from the Perl / Unix world, where it’s common to write short scripts for processing output from other programs.

Let’s see an example of how this works:

This code will print "Program starting..." before it prints 123. It could be useful if you are writing the kind of short scripts that this is meant for, but probably not very useful in web applications.

Update:
Reader Ronald sent me some interesting uses for this trick. Here is what he said:

"It is very useful, for example for fiddling with the RUBYLIB path for the 'require' statements, because it is guaranteed to be executed before all the 'require'. I also use it to set $VERBOSE to true, or set some environment variables, etc."

14

Flip-Flop

I don’t even know why this is a thing, but I would advice to stay away from it because it can be confusing & most people are not familiar with this feature 🙂

But it could be useful to know in case you find this in other people’s code.

This is the syntax:

The idea is that once the first condition is true an invisible “switch” will turn on & everything from there will evaluate as true until the 2nd condition is true.

Example:

This prints all the numbers from 3 to 15, but if you skip 15 it will keep printing.

15

Redo Keyword

Another keyword that you don’t see very often is redo, this allows you to repeat the same iteration inside a loop…

…but unless you use next or break you will have an infinite loop. So I think you should not use this feature.

Conclusion

You learned about a few cool Ruby tricks & tips. If you want more see my other post here.

Don’t forget to share this post so more people can see it!

18 comments
Kiran Kumar Chirravuri says a couple of months ago

cool…
learned something new..☺

    Jesus Castello says a couple of months ago

    Thanks for reading 🙂

Ben Polinsky says a couple of months ago

Ah, the destructuring of block arguments is cool. I see you can do a.each {|(a)| # something with a} and discard b, any way to discard the first argument? This throws an error as ruby tries to assign nil: a.each {|(nil, b)| # something with b}.

    Jesus Castello says a couple of months ago

    Hey Ben,
    you could try a.each { |(_, b)| # something with b }, that’s the general convention for what you are trying to do.

Tom Cloyd MS MA LMHC says a couple of months ago

Interesting, fun, maybe even useful. As a perpetual Ruby amateur (in the fullest sense of the word) I much appreciate and always read your posts.

    Jesus Castello says a couple of months ago

    Thanks for reading Tom 🙂

Nishutosh says a couple of months ago

Awesome.
Looking forward to some metaprogramming tricks as well.

Ruberto Paulo says a couple of months ago

Number 9 is especially useful when it comes to feature flagging ruby/rails upgrades. You can wrap up deprecated methods and then push the code for testing.

Serguei Cambour says a couple of months ago

Thank you so much for sharing, it is always good to discover the new !

kaikuchn says a couple of months ago

I sometimes use the character literal for calls to split (e.g., "snake_cased_string".split(?_)) or when building a string consisting of n times the same symbol (e.g., ?**5 for "*****") even though rubocop yells at me not to do this 🙂

Avdi Grimm shows an example where the redo keyword comes in handy in rubytapas episode 259 (only members can access it), but I’d agree that it is something that one usually does not need and even then there’s probably more idiomatic ways to go about it.

    Jesus Castello says a couple of months ago

    Thanks for your comment @kaikuchn. I have to agree with Rubocop on this one, but still interesting uses 🙂

william selig says a couple of months ago

For #8, ?a syntax, I find it more useful for intention documentation purposes. For example, using this in a comparison or assignment conveys that we are specifically interested in a single character. As well, you don’t incur the potential interpolation check overhead when doing like “a” vs ‘a’.

Josh Cheek says a couple of months ago

Indefinite indexing: this amused me, so here’s a similar one: indefinite calling ^^

Destructuring: There is also some limited support for nested destructuring

And you can destructure hashes in blocks, as well

Special Globals: There aren’t hard rules for these, they have a lot of options when they define them, so you won’t necessarily see consistent behaviour across them. Eg. $_ is scope local, but you can assign to it:

You can find their definitions by grepping MRI source for rb_define_hooked_variable and rb_define_hooked_variable.

Character Literals: My fav use is ?? as a place holder, eg I might write this, and then go back and figure out what those vars are

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.

RbConfig Module: I totally didn’t realize about host_os! That will be useful, ty!

Chaining the Shovel Operator: Note that this is b/c Array#<< returns self, if it didn’t, then this wouldn’t be true (compare to assignment, which always returns the assigned value)

BEGIN & END

I think they come from awk, they’re useful on the command line when you use the -n and -p flags, eg 5 most common words in parse.y

Flip-Flop

Another command-line one, the best use cases for it have shortcuts, eg directly dropping $. will match line numbers and dropping regexes into it will match the current line (this is actually a boolean thing, not a flip-flop thing). Sadly, .. vs ... chooses whether it will test the second condition on the first line rather than whether it will include the last line, which would have been more useful, IMO.

Eg: Print the environment variables section of Ruby’s man page:

$ man ruby | col -b | ruby -ne 'print if /^ENV/.../^\w/'

    Jesus Castello says a couple of months ago

    Thanks for your comments Josh! Very interesting additions 🙂

Luis Flores says a couple of months ago

Number 5 does not work as you mention, it asigns 1 to ‘first’ and empty to ‘last’ and then 2 to ‘memo’ at least in my Ruby 2.3.0 on Mac

    Jesus Castello says a couple of months ago

    Sorry I made a mistake when copying the code from my notes. Should be working now 🙂

Michael Kohl says a couple of months ago

Re 1: Way back in the day people used DATA sections (everything after __END__) at the end of Ruby scripts for storing data. Here’s a blog post on this: http://blog.honeybadger.io/data-and-end-in-ruby/

Re 2: This works because :: is used for scope resolution in Ruby: https://en.wikipedia.org/wiki/Scope_resolution_operator#Ruby

Re 6: The special variables become a lot less magic if you require 'English: https://ruby-doc.org/stdlib-2.3.3/libdoc/English/rdoc/English.html

Re 8: I mainly use them in code golf 😉 Or when I want to be really explicit about expecting a one character string.

Re 13 and 14: both the BEGIN and END block as well as the flip-flop operator are remnants of Ruby’s Perl legacy. Though it’s been a long time since I actually saw them in code.

Now for some of my personal favorites:

*) Inheritance: the right-hand side of < can be any valid Ruby expression as long as it resolves to a class.

class IdentityCrisis < [Array, Hash].sample ; end

*) Unary minus: to define a unary minus operation, you have to use -@.

Also if you wanna confuse your friends, make them guess what this does: (1..5).map(&:-@) 😉

Infinity:

Before Float::INFINITY was added in 1.9 we used to make our own: Inf = 1 / 0.0 #=> Infinity

Destructuring addendum: fairly obvious, but restructuring works for assignments as well:

    Jesus Castello says a couple of months ago

    Thanks for your contribution Michael 🙂

Comments are closed