Ruby is awesome! If you think it’s not, you just haven’t got an opportunity to explore the simplicity, elegance and power of Ruby.
A lot of web services and enterprise level platforms use Ruby. Which ones? Twitter, Shopify, Crunchbase, Groupon. What about software? Top orchestrators - Puppet and Chef - are written in Ruby. Millions of user and thousands of developers love this language. And to love it even more, let’s go through some tips and tricks that will make your Ruby code beautiful. Here are tricks provided by Ruby on Rails develompent company RW.
1. Organize your list of values into a hash
Say, you have a list of values, and to make it easy to process them, why not create a hash? The syntax is pretty straightforward - Hash[...]. Here’s a short example:
Hash['key1', 'value1', 'key2', 'value2'] # => {"key1"=>"value1", "key2"=>"value2"}
2. Lambda Literal ->
Lambda expressions is the new big thing in Java 8. Ruby’s not lagging behind. Lambdas are an excellent way to define scopes in Ruby and if you did not know that you do now! Welcome, Lambda Literal ->
a = -> { 1 + 1 } a.call # => 2 a = -> (v) { v + 1 } a.call(2) # => 3
3. What Double stars (**) can do
The double star is a neat little trick in Ruby. See the following method:
OK, let’s take a look at the below method. It features a double star:
def my_method(a, *b, **c) return a, b, c end
Who is who here? It’s clear enough that ‘a’ is just an ordinary parameter. Nothing fancy here. *b is commanded to take all parameters after the first one. These parameters will be saved in an array. **c accepts all parameters passed after the method call (at the end of it).
Here are some examples to illustrate it:
One parameter
new_method(1) # => [1, [], {}] 1+ parameters new_method(1, 2, 3, 4) # => [1, [2, 3, 4], {}] Several parameters and hash-style parameters new_method(1, 2, 3, 4, a: 1, b: 2) # => [1, [2, 3, 4], {:a=>1, :b=>2}]
As you can see, you can easily organize data in a way that makes it easy to process and re-use in your code.
4. Arrays and objects should be handled exactly 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).
In your code you may choose if or not you want to accept an array. Sometimes, you should only process a single object. Of course, you may check what kind of object you have received. But that’s an extra line of code and additional logic.
Here are two examples of working with arrays and single objects. First off, let’s define variables.
variable = 1 variable _arr = [1, 2, 3]
Now, let’s loop through using [*...]:
[*variable ].each { |s| s } [*variable _arr].each { |s| s }
It’s time to work with an array - Array(...).
Array(variable ).each { |s| s } Array(variable _arr).each { |s| s }
5. Double Pipe Equals ||=
The Double Pipe Equals is a great tool to write concise code. Double pipe equal is a cool thing! Some examples never hurt:
a || a = b # Correct
However, some folks will think of this one:
a = a || b # Wrong
Why is it wrong? Well, why reassign variable a? We have it already!
Now, let’s perform some calculations:
def total_sum @total ||= (2..10000000).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.
This method will perform calculation only having been called the first time! How cool is that, huh?
6. Ask for parameters to be accepted: Mandatory hash parameters
This is a Ruby 2.0 feature. The traditional way to define a method that take a hash of parameters is the following:
def new_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.
However, you may go further and specify what keys and default values such a method expects:
def new_method(a:, b:, c: 'value1') return a, b, c end
Let’s call this method with various parameters passed over:
new_method(a: 2) # => ArgumentError: missing keyword: b
Why didn’t the interpreter complain over missing c? It’s because it already has a predefined value in the method declaration. Here’s an example:
new_method(a: 2, b: 3) # => [2, 3, "value1"]
And now let’s pass all 3 values:
new_method(a: 1, b: 2, c: 3) # => [1, 2, 3]
There’s a more elegant way to pass parameters, for instance saving them to a hash and then passing this hash to the method:
hash = { a: 1, b: 2, c: 3 } new_method(hash) # => [1, 2, 3]
7. How to easily generate numbers or alphabet
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.
For some reason, you may need to generate an alphabet or just a pre-defined list of numbers. Defining a range in Ruby is a piece of cake.
English alphabet:
('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"] Number from 1 to 11 (1..11).to_a # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
8. Improving your code with taps
A tap can make your code more readable. Let’s create a simple class:
class User attr_accessor :a, :b, :c end
Now, let’s define a method that creates a new user with a sect of attributes. Here’s a traditional way:
def new_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 new_method User.new.tap do |o| o.a = 1 o.b = 2 o.c = 3 end end
The object being called is saved to a block and is then returned.
9. Default value for hash
If some value is not defined in a hash and you attempt to access it, you’ll get nil. However, this behavior can be changed. Make sure you do it with caution!
Here’s an example of defining the default value to be 0, so we get 0 back but not nil.
a = Hash.new(0) a[:a] # => 0
Easy! You can define anything here. An empty hash? No problems!
a = Hash.new({}) a[:a] # => {}
Maybe a random string? OK, let’s do it:
a = Hash.new('rubyrules’’) a[:a] # => rubyrules"
10. heredocs: how to make your code prettier
EOT is sensitive to leading spaces. So, your code will look like this:
def my_method <<-EOT Hello World EOT end
That works, but there’s a way to better format this chunk of code. Let’s use gsub method with a simple regex that will remove leading spaces. Automation rules:
def my_method <<-EOT.gsub(/^\s+/, '') Hello World EOT end
Sure, this is just a small token of knowledge that you can get on Ruby. But hopefully, it should be a good start!
Comments will be moderated and
rel="nofollow"
will be added to all links. You can wrap your coding with[code][/code]
to make use of built-in syntax highlighter.Hash.new { |h, k| h[k] = [] }
more explanation here
http://stackoverflow.com/questions/2698460/strange-behavior-when-using-hash-default-value-e-g-hash-new#answer-28916684
There's one slight caveat in point 9 though. When passing a mutable object into Hash::new, that one instance will be used as the default value.
This can lead to some side effects:
To avoid this, use a default proc, which creates a new hash for each missing key: