Ruby is an interesting language. But when it comes to comparing it to giant classic languages like C or Java, it’s actually quite new. For those who are familiar with these classic languages, it’s not so simple to approach Ruby’s syntax even though it’s language is so close to the verbal language.

In addition, because of its flexibility, you may not know which symbol to use or you may not even know if it exists. Today, we’ll review some tips that Ruby ninjas use in order to optimize their code. After reviewing this, we’d recommend using them in your daily coding or at least not to be confused when reading Ruby code from Ruby experts.

Shall we begin?

The Basics

Basic shortcuts

First, in Ruby, there are some succinct ways to create some kind of object like [] to create array or {} to create Hash (or block/proc). Other than that, we can:

String

%{} or %Q{} are different ways to represent a double quote string and they can store string interpolation. By using this way, you don’t need to care about the annoying double quote character () like working with a standard string and a double quotation:

irb(main):001:0> %{Hi! I am a string!}

=> "Hi! I am a string!"

irb(main):002:0> %Q{Me too! "_"}

=> "Me too! \"_\""

irb(main):003:0> %{You're 5. I am older than you 2 years old, so I am #{5+2} years old.}

=> "You're 5. I am older than you 2 years old, so I am 7 years old."

On the other hand, %q{} is equivalent to a single quote string. It means that you cannot use string interpolation when it comes to age calculation like the above example.

irb(main):004:0> %q{#{2 + 5} equals to?}

=> "\#{2 + 5} equals to?"

Array

%w and %W can be used as what String#split can do. It splits a string into words by spaces. If you want to escape some spaces, you can use \ character like escaping a quotation character from a string. The difference between %W and %w is that %W allows string interpolation.

irb(main):005:0> %w{Fruits\ I\ like: oranges apple banana}

=> ["Fruits I like:", "oranges", "apple", "banana"]

irb(main):006:0> %W{I\ ate #{1+8}\ apples\ today}

=> ["I ate", "9 apples today"]

Regex

Usually, // is used to express a Regular Expression but if you want to escape the / character, you can use %r as below:

irb(main):001:0> %r{%d/%d}

=> /%d\/%d/

Symbol

Similar to the above example, we can use %s to create symbols instead of : or :”” to escape special characters. One note, %s does not support string interpolation.

irb(main):002:0> %s{studyId}

=> :studyId

irb(main):003:0> %s{hi:man}

=> :"hi:man"

irb(main):004:0> %s{id#{1+2}}

=> :"id\#{1+2}"

irb(main):005:0> :"id#{1+2}"

=> :id3

Shelling out

When text is wrapped in backquotes (or backticks), the text inside of it is passed to a special function named Kernel.`. This function executes the content inside the quotes like in a shell command and returns a string of results. Instead of using backticks you can use %x instead. It supports string interpolation as well.

irb(main):006:0> `echo welcome 2019!`

=> "welcome 2019!\n"

irb(main):007:0> `echo welcome #{2018+1}!`

=> "welcome 2019!\n"

irb(main):010:0> %x{echo welcome #{2018+1}!}

=> "welcome 2019!\n"

Lambda literal

This is a simple way to define scope in Rails by using ->:

irb(main):013:0> add = -> (a, b) { a + b }

=> #<Proc:0x007f80028cce98@(irb):13 (lambda)>

irb(main):015:0> add.call(1, 2)

=> 3

Sneak Peek

Something more interesting

We will now give you a sneak peek into some Ruby tricks that you may not have come across yet if you haven’t been coding Ruby for very long. If you master these tricks, you will be sure to distinguish your Ruby abilities from the rest of the pack.

Parameter with *, ** prefix

Take a look at this function:

def my_func  a, *b, **c

   return a, b, c

end

In this function, a is a normal parameter, With b, all arguments get passed to the function except a, which will be stored in b as an array. And finally with c, if you pass arguments by key-value type at the end of the function calling, they will be stored in c:

irb(main):001:0> def my_func a, *b, **c

irb(main):002:1>   return a, b, c

irb(main):003:1> end

=> :my_func

irb(main):004:0> my_func 1, 2, 3, 4, a: 5, b: 6

=> [1, [2, 3, 4], {:a=>5, :b=>6}]

irb(main):005:0>

Handle objects like an array

Sometimes, you need to handle input data with flexible types, maybe it’s an object or it’s an array. Normally, you need to check if it’s an array or not. But by using this trick, you can treat your object like a normal array with [*object] or [*array] or Array(something).

irb(main):005:0> number = 1

=> 1

irb(main):006:0> array = [2, 3, 4]

=> [2, 3, 4]

irb(main):007:0> [*number].each { |s| s }

=> [1]

irb(main):008:0> [*array].each { |s| s }

=> [2, 3, 4]

Tap method

tap is an interesting method. It’s used to make manipulations on objects before returning them. tap was created for tapping into method chains, it just allows you to do something with an object inside of a block, and to always have that block returned to the object itself. So the code:

def something

 result = operation

 do_something_with result

 result

end

can be turned to:

def something

 operation.tap do |op|

   do_something_with op

 end

end

Copy Objects

Deep copy

When you copy an object, it means that you copy the reference to the copied object. As you can see:

irb(main):009:0> fruits = %w(apple banana orange)

=> ["apple", "banana", "orange"]

irb(main):010:0> new_fruits = fruits

=> ["apple", "banana", "orange"]

irb(main):011:0> fruits.map(&:object_id)

=> [70109297139200, 70109297139180, 70109297139160]

irb(main):012:0> new_fruits.map(&:object_id)

=> [70109297139200, 70109297139180, 70109297139160]

irb(main):013:0> fruits.object_id

=> 70109297139120

irb(main):014:0> new_fruits.object_id

=> 70109297139120

By using Marshall class, you can create an deep copy object:

irb(main):015:0> complete_new_fruits = Marshal.load Marshal.dump(fruits)

=> ["apple", "banana", "orange"]

irb(main):016:0> complete_new_fruits.object_id

=> 70109305512340

irb(main):017:0> complete_new_fruits.map &:object_id

=> [70109305512320, 70109305512280, 70109305512260]

For example, if I have an array of strings and I want to capitalize all the elements. Normally, you can write something like this:Using & to create procs

irb(main):018:0> fruits = ['banana', 'apple', 'orange']

=> ["banana", "apple", "orange"]

irb(main):019:0> fruits.map { |f| f.upcase }

=> ["BANANA", "APPLE", "ORANGE"]

With & operator, it’s more elegant:

irb(main):021:0> fruits.map &:upcase

=> ["BANANA", "APPLE", "ORANGE"]

The & operator takes the method caller (the fruits object), and call the to_proc method on that object. If that object is a symbol, the to_proc function will create a proc and call the method with the name corresponding to the symbol via send method.

So the above example is equivalent to:

irb(main):023:0> fruits.map {|f| f.send(:upcase)}

=> ["BANANA", "APPLE", "ORANGE"]

Now, instead of calling the instance method, we can do something like:

def demo_method(word)

 word + ' - ' + 'demo'

end

# Instead of:

res = arr.map{|str| demo_method(str)}


# We can:

res = arr.map(&method(:demo_method))

Conclusion

So as you can see the Ruby language is similar and different in many ways. Like with many things, the more experience and practice you have working with Ruby, the more skilled of a Ruby developer you will become.

So what are you waiting for? Get coding!

pangara_logo

Think you have what it takes to join our exclusive network of freelance developers and programmers? Learn more about becoming a Pangara Talent today.