DEV Community

Cover image for Jozef Behr | 10 Ruby tricks to improve your code (or not)
Jozef Behr
Jozef Behr

Posted on

Jozef Behr | 10 Ruby tricks to improve your code (or not)

Hello DEV's Myself Jozef Clifford Behr, 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"}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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, [], {}]
Enter fullscreen mode Exit fullscreen mode

More than one parameter

my_method(1, 2, 3, 4)
# => [1, [2, 3, 4], {}]
Enter fullscreen mode Exit fullscreen mode

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}]
Enter fullscreen mode Exit fullscreen mode

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]
Enter fullscreen mode Exit fullscreen mode

In the following example, I use [*...] to loop through whatever is given.

[*stuff].each { |s| s }
[*stuff_arr].each { |s| s }
Enter fullscreen mode Exit fullscreen mode

Same in this one but using Array(...).

Array(stuff).each { |s| s }
Array(stuff_arr).each { |s| s }
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

And not this one, as a lot of people think:

a = a || b # Wrong
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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"]

Enter fullscreen mode Exit fullscreen mode

Or with all of them.

my_method(a: 1, b: 2, c: 3)
# => [1, 2, 3]
Enter fullscreen mode Exit fullscreen mode

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]
Enter fullscreen mode Exit fullscreen mode

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"]

Enter fullscreen mode Exit fullscreen mode

1 to 10

(1..10).to_a
# => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

We can pass anything to the Hash initializer. Let’s try with a hash!

a = Hash.new({})
a[:a]
# => {}
Enter fullscreen mode Exit fullscreen mode

Or a weird string:

a = Hash.new('lolcat')
a[:a]
# => "lolcat"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

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!

Top comments (0)