Ruby Syntax#

Program Flow#

Ruby is quite similar to the other general-purpose programming languages and not so far from the Shell scripts: the interpreter reads the program from the top, evaluates each expression and stores the values in the variables. The script below will print the famous phase “Hello, world.”. print is the command to print to the stdout, but unlike puts it is not adding newline at the end.

print "Hello, "
puts "world."

More than one expression can be written in one line - in this case you must put the semicolon ; between them. The good practice is to avoid it for readability, but this could be useful in one-liners, like ruby -e ‘print “Hello, “; puts “world.”’. The script below is the same as the previous one.

print "Hello, "; puts "world."

Ruby treats end of the line as the end of the expression, except there is an operator (like + or -), colon or backslash at the end of the line. In this case the next line is a continuation of the previous statement. When you define a string using single or double quotes, interpreter treats the newline as a part of the string, until the closing quote.

a = 1 +         # the same as 'puts 1 + 3'
    2
puts a          # prints '3'

puts 1,         # the same as 'puts 1, 2'
     2          # prints '1', newline and '2'

puts 1 \        # the same as 'puts 1, 2'
    ,2          # prints '1', newline and '2'

puts 'Hello' \  # the same as "puts 'Hello' 'world.'"
     ' world.'  # prints 'Hello world'

puts 'Hello
world'          # prints 'Hello', newline and 'world'

Comments#

Everything begins with hash # to the end of the line is treated as a comment and it is not evaluated. There are multi-line comments as well - everything between lines =begin and =end is not evaluated by the interpreter.

# this is a comment
=begin
this is a comment as well
=end

Variables and Constants#

The local variable starts with a small letter and may contain letters, digits and underscore _ sign. The good practice is to use snake case instead of camel case to name the variables, but it is just a convention.

number_one = 1
number_two = 2
sum = number_one + number_two
puts sum

The global variable must start with dollar symbol $, then lowercased variable name. The scope of this variables is global, so they can be used anywhere in your script (in opposite to local variables, which lives only within the given function).

$hello = 'hello'
$world = 'world'
puts $hello + ' ' + $world

Snake case is a practice of naming symbols which contains words or elements using underscode as a separator, for example: is_file_executable or server_name. In snake case, only lowercase characters are used. Camel case uses uppercase letters for element separation, like: isFileExecutable or ServerName.

Constant is a kind of variable, which should not be changed. Constant syntax is very similar to variable, but it must start with the capital letter. Most programmers are using only capital syntax for this:

NUMBER_ONE = 1
NUMBER_TWO = 2
SUM = NUMBER_ONE + NUMBER_TWO
puts SUM

Be advised that in Ruby the constants are not very far from variables and you can change it - it is just giving a warning. In a session below, we’ve changed the constant content from “Hello, world” to “Hello, world!!!”. Ruby gives the warning, but still allows to change the content.

HELLO_WORLD='Hello, world'
#=> "Hello, world"
HELLO_WORLD='Hello, world!!!'
(irb):11: warning: already initialized constant HELLO_WORLD
(irb):10: warning: previous definition of HELLO_WORLD was here
#=> "Hello, world!!!"
HELLO_WORLD
#=> "Hello, world!!!"

Ruby is case sensitive which means that the symbol serverOne is different than serverone.

Methods#

Methods (aka functions, procedures) are defined using def keyword, and should begin with lowercase character. Good practice is to use snake case for method names, just like for variables. The definition finishes with end keyword. Here is a method to print well-know sentence:

def hello_world
  puts "Hello, world"
end

If you run the script above, nothing will happen. This is because the method has been defined, but not invoked yet. You need to run it by simply write its name:

def hello_world
  puts "Hello, world"
end
hello_world  # invoke method defined above

Notice that there is no need to use parenthesis in Ruby when they are not really required to avoid confusion. It is completely up to you, you may write puts(“Hello world”) instead of puts “Hello world”.

It must be no space between method name and the parenthesis.

def hello_world()
  puts("Hello, world")
end
hello_world()     # invoke method defined above

Methods may have the arguments, given as comma-separated list of names in parenthesis after the name. And the methods always return a value of last expression evaluated in its body. Or you can stop the flow and return the value using return keyword. Consider two functions below:

def sum(first_number, second_number)
  first_number + second_number
end
the_sum = sum 2, 2
puts the_sum   # prints '4'

def another_sum(first_number, second_number)
  return first_number + second_number
  2 + 2        # this line will never be evaluated
end
puts(another_sum(2, 3))    # prints '5'

Function sum, defined in lines 1 - 3, takes two arguments, adds them and returns value of this addition - the last expression. Fourth line invokes sum function with arguments: first_number = 2, second_number = 2, gets the return value of 2 + 2 and assigns the value to the new variable the_sum. The second method uses return keyword to declare stricly where to exit the function and what to return. Notice the last expression 2 + 2 is not evaluated at all, because return breaks method flow immediately.

Take a look at the line 11: here, the interpreter will evaluate the value of another_sum(2, 2) and will pass the return value of it directly to the puts method. There is no need to use intermediary variable, like in the first example.

Notice the methods in the 11th line are invoked with parenthesis. We did it by the reason: to avoid human ambiguity. From the interpreter point of view this construction is the same as puts another_sum(2, 3) or even puts another_sum 2, 3. In this case it is quite clear, but what if we want to pass two arguments to puts (puts can take any number of arguments: it prints each of them in a new line)? For example, to print out the result of another_sum 2, 3 and a number 5. In this case the proper expression is puts(another_sum(2, 3), 5) or even puts another_sum(2, 3), 5 but not puts another_sum 2, 3, 5 - because in this case interpreter will try to find out the method another_sum which tooks three arguments. To avoid it, use parenthesis in ambigious expressions, for code readability as well.

Here documents#

Here document is a construction known from the Unix Shell, allows to build a string from the multiple lines. Like in the Shell, you must specify a symbol used to identify the end of the string preceded by <<. Notice there must be no space between << and the identifier.

str = <<EOF
Hello
world
EOF
puts str   # prints 'Hello', newline, 'world'

Loading Ruby Files#

There are two commands to load external Ruby source files (equivalent to Shell command source): load and require. The first one just loads and executes the given Ruby source file, the second one is more complex: it is loading the file only once. The argument to require command is a file name without “.rb” extention. It is searching for the file in the path given in global variable $LOAD_PATH (like PATH in the Shell). By default load path does not contain current directory, so you need to do require ‘./filename’ if you want to load file from the current directory, or modify LOAD_PATH content.
The example below assumes there is a file test.rb in a current directory contains only one line: puts ‘loaded’:

load 'test.rb'                 # load the file from current directory
loaded
#=> true

load '/Users/turbo/test.rb'    # load the file again
loaded
#=> true

require './test'               # require this file for the first time
loaded
#=> true

require './test'               # require again - file not loaded again
#=> false

puts $LOAD_PATH                # content of the $LOAD_PATH
/Users/turbo/.rbenv/versions/2.0.0-p247/lib/ruby/site_ruby/2.0.0
/Users/turbo/.rbenv/versions/2.0.0-p247/lib/ruby/site_ruby/2.0.0/x86_64-darwin13.1.0
/Users/turbo/.rbenv/versions/2.0.0-p247/lib/ruby/site_ruby
/Users/turbo/.rbenv/versions/2.0.0-p247/lib/ruby/vendor_ruby/2.0.0
/Users/turbo/.rbenv/versions/2.0.0-p247/lib/ruby/vendor_ruby/2.0.0/x86_64-darwin13.1.0
/Users/turbo/.rbenv/versions/2.0.0-p247/lib/ruby/vendor_ruby
/Users/turbo/.rbenv/versions/2.0.0-p247/lib/ruby/2.0.0
/Users/turbo/.rbenv/versions/2.0.0-p247/lib/ruby/2.0.0/x86_64-darwin13.1.0