DEV Community

Nissrine Canina
Nissrine Canina

Posted on

Ruby Fundamentals, Compare and Contrast with Javascript

The picture is showing a ruby gem for Ruby and JS logo for Javascript

Learning Ruby Coming from Javascript

Novice programmers often get intimidated by the idea of learning a new language. That is where the idea of this blog comes from. As a student in the Flatiron School, I spent my first half of the program learning Javascript and its framework React (the front-end side). When the time comes to switch gears, Ruby comes into play to code the back-end side of our programs. It was natural to compare and contrast Ruby and Javascript along the way to understand their similarities and differences. The purpose of this blog is to help anyone, new to Ruby, learn its basic concepts and fundamentals.

Introduction to Ruby

It is important to note that Ruby is primarily an Object Oriented Language (OOP) whereas Javascript is not strictly OOP; however, Javascript provides features such as classes and objects which are inspired by OOP. So, what is OOP? OOP is a type of programming based on the concept of "objects" which can contain data in the form of fields (often known as attributes or properties), and code in the form of procedures (often known as methods).OOP is about structuring code so that its functionality can be shared throughout the application program. On the other hand, Javascript is procedural programming language by nature where programs are built in sequential order and functions are called to share their behavior. Javascript can be an OOP language but it was not originally designed as an OOP language. The OOP syntactic sugar was added later on. Understanding this concept will explain the key differences between Ruby and Javascript syntax.

Language Purpose

Javascript

build client-side applications that run in the browser.
Work in the browser environment/sandbox where we can access:

  • Make network requests
  • Update the DOM
  • Listen for events
  • Debug our code in the browser's developer tools

Ruby

build server-side applications.
take advantage from our computer system:

  • Read and write files
  • Listen for network requests and send responses
  • Connect to a database to access and update data we can build all kinds of apps not just web apps Command line interfaces Web servers Games Web scrapers

Terminal Output Methods

One of the main differences between Javascript and Ruby is that Ruby code run from the terminal using the Ruby interpreter whereas Javascript run code in the browser.

The command ruby -v is used to check which Ruby version is used in the system.

To run Ruby application use the command ruby some_file.rb, where some_file is the name of the file where Ruby code is written.

Any code written in some_file.rb can be outputted to the terminal using Ruby's various methods for printing output: puts, print, p, and pp.

puts and print are both used to print strings to the terminal with a difference of a line break added at the end of each string when puts is used.

If we run this code:

puts "I am learning Ruby!"
puts "I am learning Ruby!"
puts "I am learning Ruby!"
Enter fullscreen mode Exit fullscreen mode

We will receive this output in the terminal:

I am learning Ruby!
I am learning Ruby!
I am learning Ruby!
Enter fullscreen mode Exit fullscreen mode

If we run the same code using print:

print "I am learning Ruby!"
print "I am learning Ruby!"
print "I am learning Ruby!"
Enter fullscreen mode Exit fullscreen mode

We will receive an output without a line break:

I am learning Ruby!I am learning Ruby!I am learning Ruby!%  
Enter fullscreen mode Exit fullscreen mode

To inspect a non string data, p would be a better choice compare to puts because the latter one attempts to convert everything to a string by calling the .to_s method. On the other hand, p calls the .inspect method which will present data in a nicer format.

puts [1, 2, 3, 4]
1
2
3
4
 => nil 

#`puts` will convert `nil` to an empty string

puts [1, 2, nil, nil, nil, 6]
1
2



6
 => nil 
Enter fullscreen mode Exit fullscreen mode

p will return a raw version of an object (i.e including quotes and new line characters). puts will always return nil.

p "Hello World!"
"Hello World!"
 => "Hello World!" 

p "Hello World!\n"
"Hello World!\n"
 => "Hello World!\n" 
Enter fullscreen mode Exit fullscreen mode

p is more useful for debugging purposes whereas puts is useful for display to the user.

pp is used for printing nested and complicated arrays and hashes. pp calls the .pretty_inspect method to print the data in an organized and easy to read fashion.

[{:id=>1, :color=>"blue"},
 {:id=>2, :color=>"red"},
 {:id=>3, :color=>"yellow"}]
Enter fullscreen mode Exit fullscreen mode

In Javascript, console.log would have the equivalent function to puts in Ruby.

Data Types in Ruby

Strings

Strings in Ruby can be defined with single or double quotes similarly to Javascript:

   "I am a string!"
   'I am also a string!!'
Enter fullscreen mode Exit fullscreen mode

Since Ruby is an OOP language, we can call several methods on string literals (i.e. "hello"). Each string in ruby is actually an instance of the class String. Therefore, class methods are available to its instances. We can check look up these methods via "example".methods.

"hello".upcase
# => "HELLO"
"hello".capitalize
# => "Hello"
"hello".reverse
# => "olleh"

Enter fullscreen mode Exit fullscreen mode

String Interpolation

String interpolation exists in both Ruby and Javascript; however, backticks have a different purpose in Ruby:

# Ruby (comment in Ruby)
name = "Joe"
puts "Hello #{name}"

Enter fullscreen mode Exit fullscreen mode
// JavaScript (Comment in Javascript)
const name = "Joe";
console.log(`Hello ${dogName}`);

Enter fullscreen mode Exit fullscreen mode

Numbers

There are two types of numbers in Ruby: integers as whole numbers and floats as decimal numbers. Ruby provides several methods to work on both types of numbers.

> 2.3.floor
 => 2
> 8.5.ceil
 => 9

Enter fullscreen mode Exit fullscreen mode

Also, we can convert strings to numbers:

> "2.5".to_i
 => 2 
> "2".to_i
 => 2 
> "2".to_f
 => 2.0
Enter fullscreen mode Exit fullscreen mode

Unlike Javascript, Ruby will not convert an integer to a float during the process of arithmetic operations unless one of the sides is a float:

> 5/4
 => 1 
> 5/4.to_f
 => 1.25 
> 5/4.0
 => 1.25 

Enter fullscreen mode Exit fullscreen mode

Nil

In Ruby, there is only one case of absence of value which is represented by nil. For example, puts will always return nil. On the other hand, Javascript has two different datatypes that represent the absence of a value null and undefined. The latter one is commonly seen when we create a variable and we do not assign a value to it. Ruby will not allow the creation of a variable without assigning a value to it. If we intent to create a variable and not assign it a value, we must explicitly assign nil to declare an empty value.

 puts "Return something"
 # Return something
 # => nil
Enter fullscreen mode Exit fullscreen mode
 > name
 NameError (undefined local variable or method `name' for main:Object)

> name = nil
 => nil 
> 
Enter fullscreen mode Exit fullscreen mode
 let someValue;
console.log(someValue);
// => undefined
someValue = null;
console.log(someValue);
// => null
Enter fullscreen mode Exit fullscreen mode

Booleans

Booleans have two values: true and false like in Javascript. In Ruby, however, true is an instance of TrueClass and false is an instance of FalseClass.
Additionally, only nil and false are falsy values. Everything else is truthy including 0 and empty string"". On the other hand, in Javascript, null, undefined, 0, false, "", and NaN are falsy values.

Symbols

The symbol data type (:symbol_example) exists in both Ruby and Javascript yet the use of symbols is more common in Ruby where symbols are used as keys on a hash (a hash is equivalent to an object in Javascript). While a symbol is a representation of data similar to a string, Ruby allocates the same space in memory for symbols versus a string which is allocated a different space in memory each time it is called:

 > :some_symbol.object_id
 => 2077788 
 > :some_symbol.object_id
 => 2077788 
 > "a string".object_id
 => 260 
 > "a string".object_id
 => 280 
 > 

Enter fullscreen mode Exit fullscreen mode

Arrays

Arrays have similar functionality in both Ruby and Javascript. They can be created using literal or class constructors:

 > [3, 6, 9]
 => [3, 6, 9] 

 > Array.new
 => [] 
Enter fullscreen mode Exit fullscreen mode

The Ruby documentation https://www.ruby-lang.org/en/documentation/ provides a comprehensive list of methods to perform CRUD actions (create, read, update, delete) in addition to operating on arrays as well as elements within an array. Some of these methods can work for both Ruby and Javascript arrays, some methods in Javascript have equivalents methods in Ruby, and some others are exclusive to Ruby.
Similarly to Javascript, we can check elements in an array by index in Ruby:

 #Ruby
 > my_array = [3, 6, 9, 12, 15]
 => [3, 6, 9, 12, 15] 
 > my_array[0]
 => 3 
 > my_array[-1]
 => 15  
Enter fullscreen mode Exit fullscreen mode

Ruby has a wide selection of enumerable methods that allows us to traverse, search, and sort through arrays. Some enumerables are used interchangeably in Ruby as well as in Javascript to loop over elements of an array. Some examples consist of but not limited to .map, .filter. .each, and .find. Ruby has a version of .map called .collect and .select which is equivalent to .filter.

Ruby has convenient methods to check first and last elements on a given array: Array.first and Array.last respectively compare to Javascript. For instance, to check the last element on an array with an unknown size we use: Array[Array.length-1]. And, to check the the length of an array in Ruby we use Array.size.

To extract a range of element from an array in Javascript, we can use the slice method. The slice method does not mutate the original array and it stops extracting elements before the last designated index. For instance: slice(1,3) will extract the element with index 1 [1] and exclude the element with index 3 [3]:

 //Javascript
 someArray = [1, 2, 3, 4, 5, 6]
 (6) [1, 2, 3, 4, 5, 6]
 someArray.slice(1,3)
 (2) [2, 3]
 someArray
 (6) [1, 2, 3, 4, 5, 6]
Enter fullscreen mode Exit fullscreen mode

In Ruby, we can extract a range of elements from an array using [0..2] which will return all the elements between index 0 and index 2 including the last one. But if we want to exclude last element we use the three dots method: [0...2]:

 :006 > my_array = [3, 6, 9, 12, 15]
 => [3, 6, 9, 12, 15] 
 > my_array[0..1]
 => [3, 6] 
 > my_array[0...2]
 => [3, 6] 
 > my_array[0..2]
 => [3, 6, 9] 
 > my_array[0...2]
 => [3, 6] 
Enter fullscreen mode Exit fullscreen mode

To add an element to the end of an array in Javascript we use push method whereas the shovel << method is more commonly used in Ruby:

 //Javascript
 someArray
 (6) [1, 2, 3, 4, 5, 6]
 someArray.push(9)
 7
 someArray
 (7) [1, 2, 3, 4, 5, 6, 9]

#Ruby
 011 > my_array = [3, 6, 9, 12, 15]
 => [3, 6, 9, 12, 15] 
 2.7.4 :012 > my_array << 10
 => [3, 6, 9, 12, 15, 10] 
 2.7.4 :013 > 

Enter fullscreen mode Exit fullscreen mode

Both languages have the ability to concatenate arrays, meaning combining multiple arrays, using concat() method. In Ruby, we can combine arrays using + as well:

//Javascript
 a = [1, 2, 3, 4]
 (4) [1, 2, 3, 4]
 b = [3, 6, 9]
 (3) [3, 6, 9]
 a + b 
 '1,2,3,43,6,9'
 a.concat(b)
 (7) [1, 2, 3, 4, 3, 6, 9]

#Ruby
 > a= [1, 2, 3, 4 , nil] 
 => [1, 2, 3, 4, nil] 
 > b= [6, 7, 8, 9]
 => [6, 7, 8, 9] 
 > a.concat(b)
 => [1, 2, 3, 4, nil, 6, 7, 8, 9] 

 >a= [1, 2, 3, 4 , nil] 
 => [1, 2, 3, 4, nil] 
 > b= [6, 7, 8, 9]
 => [6, 7, 8, 9] 
 > a + b
 => [1, 2, 3, 4, nil, 6, 7, 8, 9] 
Enter fullscreen mode Exit fullscreen mode

To remove first and last elements from an array, both Ruby and Javascript use shift and pop respectively.

In Ruby, there are some methods that has either a question or an exclamation mark (i.e. include? and reverse!). if a method includes a question mark, this means that the return will be a boolean value (true or false). Any method with exclamation mark will change the original array. We can keep original array by omitting the exclamation point:

 #Ruby
 > a = [1, 2, 3, 4]
 => [1, 2, 3, 4] 
 > a.reverse
 => [4, 3, 2, 1] 
 > a
 => [1, 2, 3, 4] 
 > a.reverse!
 => [4, 3, 2, 1] 
 > a
 => [4, 3, 2, 1] 
Enter fullscreen mode Exit fullscreen mode

It is also worth mentioning that some methods are simpler to use in Ruby compare to Javascript. For example, to add all elements in a given array we simply use .sum whereas in Javascript we use the reduce method: Array.reduce((sum, num) => sum + num). Another example of a simple method in Ruby is the .uniq method which returns one version of each element in an array: [1, 1, 2, 3].uniq => [1, 2, 3]. To achieve the same results in Javascript, we use the filter method array.filter((num, index, array) => array.indexOf(num)===index)

In Ruby, we can create arrays of strings and symbols as such:

 #Ruby
  %w[word word]
 => ["word", "word"] 
 > %i[word word]
 => [:word, :word] 
Enter fullscreen mode Exit fullscreen mode

Hashes

Hashes in Ruby can be compared to a plain old Javascript object. However, the term object is used in Ruby to indicate an instance of a class. Hashes are composed of key/value pairs where each key points to a value: { key1: "value1", key2: "value2" }.
Unlike Javascript, we cannot use use dot notation to access values within a hash, only bracket notation is valid with hashes:

 some_hash = { key1: "value1", key2: "value2" }
 some_hash[:key2]
 # => "value2"
Enter fullscreen mode Exit fullscreen mode

We can also create hashes with strings instead of keys: { "string1" => "value1", "string2" => "value2" }.

A hash can be converted to an array:

 > some_hash = { key1: "value1", key2: "value2" }
 => {:key1=>"value1", :key2=>"value2"} 
 > some_hash.to_a
 => [[:key1, "value1"], [:key2, "value2"]] 
Enter fullscreen mode Exit fullscreen mode

There are several methods that are available to the Hash class similarly to the Array class. The Ruby documentation https://www.ruby-lang.org/en/documentation/ provides a list of method for every class.

Methods

A method in Ruby is the equivalent of a function in Javascript:

 //Javascript
 function someFunction(parameter) {
  console.log("Running someFunction");
  return parameter + 1;
 }
Enter fullscreen mode Exit fullscreen mode
 #Ruby
 def some_method(parameter)
  puts "Running some_method"
  parameter + 1
 end
Enter fullscreen mode Exit fullscreen mode

Here are the key differences:

  • The def keyword defines a method in Ruby just as function in Javascript.
  • By convention, the name of the method some_method is in snake case whereas the name of the function in Javascript is in camel case someFunction.
  • Parameters are defined in parentheses in both languages but we can omit the parentheses if the method has no parameter.
  • the end keyword defines the method's body just as the curly parentheses do in Javascript.
  • puts is equivalent to console.log. It will output to the terminal but has a nil return value.
  • The return value in a Ruby method will be always the last line in the method's body. The return keyword can be omitted and the method will implicitly return the last line.

Method Scope

In Javascript, functions have access to variables defined in their parent scope whether the parent scope consists of another function or the global scope. In Ruby scope functions differently. Any variable defined outside of the def and end keywords is unreachable:

 guest_name = "Joe"

 def say_hello_to_guest
  puts "Hello #{guest_name}!"
 end
 => NameError (undefined local variable or method `guest_name' 
 for main:Object)
Enter fullscreen mode Exit fullscreen mode

Calling the guest_name variable from inside the method will throw an undefined local variable error. To solve the issue of an out of scope variable, we have to pass is as an argument:

 guest_name = "Joe"

 def say_hello_to_guest
  puts "Hello #{guest_name}!"
 end
 say_hello_to_guest(guest_name)
#=> "Hello Joe!"
Enter fullscreen mode Exit fullscreen mode

Variables

In Javascript, declaring a variable require either let or const keywords preceding the variable name. A let variable can be declared first before assigning a value to it whereas a const variable hoists the declaration and the assignment at the same time. We cannot declare a const without assigning a value to it. In Ruby, due to scoping issues as well as the concept of Object Oriented Programming, variables are treated differently.

Variables in Ruby:

  • Local variables: start with a lower case or an underscore(_), should snake case if more than one word is used to name the variable (i.e. name = "Sarah", pet_name = "Pup").
  • Global variables: start with a dollar sign ($) and are available in the global scope. They are rarely used because of debugging issues:
 > $guest_name = "Joe"
 => "Joe" 
 > def say_hello_to_guest
 >   puts "Hello #{$guest_name}!"
 > end
 => :say_hello_to_guest 
 > say_hello_to_guest
 Hello Joe!
 => nil 

Enter fullscreen mode Exit fullscreen mode
  • Instance variables: start with an at symbol (@) (i.e. @name = "Sarah").
  • class variables: start with double at symbol (i.e. @@name = "Sarah"). Both instance and class variables are seen within the topic of Object Oriented Programming.
  • Constant: holds data that does not change. Must be in all caps (i.e. NAME = "Sarah"). It is equivalent to const in Javascript. Scope wise, a constant can also be accessed from outside of the class using: book::GENRES. Unlike Javascript declaring a variable with a constant in Ruby does not prevent the variable from being reassigned though it will give a warning.

Debugging in Ruby

Ruby comes with its own REPLs (Read, Evaluate, Print, Loop) when installed. The first REPL is IRB (Interactive Ruby) which is similar to the browser's console in Javascript. IRB allows you to experiment some procedural programming. It is a completely new environment, separate from our code, where we have to copy and paste the blocks of code we want to test. The second REPL is 'Pry which offers more functionality than the previous one because it injects an interactive environment into our code. Pry allows more flexibility in testing our code, we just have to add binding.pry anywhere in our code similar to debugger in Javascript.

Conclusion

Learning the syntax is the first step to learn a new language. It is also crucial to understand the concept the language is built around as well as its history https://www.ruby-lang.org/en/documentation/ruby-from-other-languages/. After mastering Ruby fundamentals, the next step is to learn about Macros(getters and setters methods), initialize method, public vs private methods, self, class variables and methods, instance variables and methods, and class inheritance.

Latest comments (0)