Ruby Gotchas
14 Sep 2020
NOTE: I primarily wrote this to verify my site still works. My previous SitePoint articles are much more detailed.
1. Common Trip-ups for New Rubyists: Part 1 2. Common Trip-ups for New Rubyists: Part 2
One Space Too Many
Can't remember how many times I've hit this one. A paren-enclosed argument list will throw an error if you put a space before it.
def add(a, b) a + b endParens surrounding the arguments works as expected.
add(1, 2) =>3Removing the parens still works.
add 1, 2 =>3But if we put a space before a paren-enclosed argument list, we get a syntax error.
add (1, 2) syntax error, unexpected ',', expecting ')'
Loops Stuck on the First Iteration
Undefined variables in blocks are undefined each time the block is executed.
3.times do sum ||= 0 sum += 1 puts sum end
Results in:
1 1 1
For loops work as expected.
for i in 1..3 sum ||= 0 sum += 1 puts sum end
Results in:
1 2 3
However, it's generally not considered idiomatic Ruby, so it's better to just declare all variables that will be needed outside of the closure.
Class Variables
Ruby provides two notations for class variables, @ and @@.
class Animal @speak_type = "grr" def self.speak puts @speak_type end end class Cat < Animal @speak_type = "meow" end
Cat.speak Animal.speak
Results in:
meow grr
However, if we use a @@ variable...
class Animal @@speak_type = "grr" def self.speak puts @@speak_type end end class Cat < Animal @@speak_type = "meow" end
Cat.speak Animal.speak
We get:
meow meow
What has happened?
The assignment of @@speak_type of Cat has overwritten the value in the parent class!
This can lead to unexpected behavior, so you should always use @ class variables.
#eql? vs #equal?
#eql? compares the type and value, while #equal? compares the object_id.
x = "cat" => "cat" y = "cat" => "cat" x === y => true x.eql? y => true x.equal? y => false
String Interpolation Requires Double-Quotes
This one probably gets a lot of people that come from Python.
If you attempt to use Ruby's hash-bracket string interpolation with single quotes, it won't perform interpolation.
name = "bob" => "bob" 'Hello, #{name}' => "Hello, \#{name}" "Hello, #{name}" => "Hello, bob"
Another reason you will encounter this is because many developers assume single-quotes are faster to evaluate or due to following a style guide that recommends single quotes unless interpolation is needed. So another developer will add an interpolated value to a string without changing to double-quotes.
In this case, unless your team is already following the convention, I think it is appropriate to just always use double-quotes.