In this article, I want to show you 10 nice Ruby features that you may know or not. Anyway, it’s a quick read and it’s always interesting to learn new stuff, right?!
1. Create a hash from a list of values
You can create a hash from a list of values by using Hash[...]
. It will create a hash like below:
Hash['key1', 'value1', 'key2', 'value2']
# => {"key1"=>"value1", "key2"=>"value2"}
2. Lambda Literal ->
Introduced quite recently and the new way recommended to define scopes in Rails, the ->
sign, a.k.a Lambda Literal, allows you to create lambda easily.
a = -> { 1 + 1 }
a.call
# => 2
a = -> (v) { v + 1 }
a.call(2)
# => 3
3. Double star (**)
The double star is a neat little trick in Ruby. See the following method:
def my_method(a, *b, **c)
return a, b, c
end
a
is a regular parameter. *b
will take all the parameters passed after the first one and put them in an array. **c
will take any parameter given in the format key: value
at the end of the method call.
See the following examples:
One parameter
my_method(1)
# => [1, [], {}]
More than one parameter
my_method(1, 2, 3, 4)
# => [1, [2, 3, 4], {}]
More than one parameter + hash-style parameters
my_method(1, 2, 3, 4, a: 1, b: 2)
# => [1, [2, 3, 4], {:a=>1, :b=>2}]
4. Handle single object and array in the same way
Sometimes you might want to give the option to either accept a single object or an array of objects. Instead of checking for the type of object you’ve received, you could use [*something]
or Array(something)
.
Let’s assign two variables. The first one is a single digit and the second one is an array of digits.
stuff = 1
stuff_arr = [1, 2, 3]
In the following example, I use [*...]
to loop through whatever is given.
[*stuff].each { |s| s }
[*stuff_arr].each { |s| s }
Same in this one but using Array(...)
.
Array(stuff).each { |s| s }
Array(stuff_arr).each { |s| s }
5. Double Pipe Equals ||=
The Double Pipe Equals is a great tool to write concise code.
It’s actually equivalent to the following:
a || a = b # Correct
And not this one, as a lot of people think:
a = a || b # Wrong
The second one doesn’t make sense because there is no point reassigning a
if we already have it!
This operator can be used to create methods like this in your classes. I love to use it for calculations.
def total
@total ||= (1..100000000).to_a.inject(:+)
end
Now you could have other method calling total
to get the total value but it will only be calculated the first time.
6. Mandatory hash parameters
This one was introduced in Ruby 2.0. Instead of just defining a method that takes a hash in parameters like this:
def my_method({})
end
You can specify the keys that you are waiting for and even define default values for them! a
and b
are mandatory keys.
def my_method(a:, b:, c: 'default')
return a, b, c
end
We can try to call it without giving a value for b
but it won’t work.
my_method(a: 1)
# => ArgumentError: missing keyword: b
Since c
has a default value, we can just call the method with a
and b
.
my_method(a: 1, b: 2)
# => [1, 2, "default"]
Or with all of them.
my_method(a: 1, b: 2, c: 3)
# => [1, 2, 3]
All we are doing is passing a hash and using some visual shortcuts but obviously, you can also pass a hash like this:
hash = { a: 1, b: 2, c: 3 }
my_method(hash)
# => [1, 2, 3]
7. Generate array of alphabet or numbers
You might want to generate a list of numbers or put the entire alphabet inside an array. Well, you can use ruby ranges to do this.
A to Z
('a'..'z').to_a
# => ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
1 to 10
(1..10).to_a
# => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
8. Tap
Tap
is a nice little method that improves code readability. Let’s take the following class as an example.
class User
attr_accessor :a, :b, :c
end
Now let’s say you want to instantiate a new user and assign a value to each of its attributes. You could do it like this:
def my_method
o = User.new
o.a = 1
o.b = 2
o.c = 3
o
end
Or you could use tap
to do it like this.
def my_method
User.new.tap do |o|
o.a = 1
o.b = 2
o.c = 3
end
end
Basically, the tap
method yields the calling object to the block and returns it.
9. Default value for hash (Bad trick)
By default, when trying to access a value not defined in a hash, you will receive nil
. You can actually change this at initialization.
EDIT: Don’t do this unless you know what you’re doing. Checkout the comments below for a complete explanation.
In this first example, we define the default value to be 0 so when a[:a]
is called, we’re getting 0 back and not nil
.
a = Hash.new(0)
a[:a]
# => 0
We can pass anything to the Hash
initializer. Let’s try with a hash!
a = Hash.new({})
a[:a]
# => {}
Or a weird string:
a = Hash.new('lolcat')
a[:a]
# => "lolcat"
10. heredocs
I personally dislike seeing heredocs that break the code flow and indentation. Since EOT
takes into account the leading spaces, you usually have to stick the content to the left like this:
def my_method
<<-EOT
Some
Very
Interesting
Stuff
EOT
end
But there’s a trick to avoid that. By using the gsub
method with a short regex, you can automatically remove the leading spaces which allows you to keep your indentation consistent.
def my_method
<<-EOT.gsub(/^\s+/, '')
Some
Very
Interesting
Stuff
EOT
end
I hope you enjoyed those little tricks and I’m sure you already knew some, if not all, of them. Let me know if you have other Ruby tricks that should be added to this list! If you want to learn about one big Ruby on Rails trick, checkout Modular Rails ;)