Introducing Ruby to PHP developers

Feanor Jan 3, 2012 Computers
Ever since Ruby on Rails became popular, the Ruby programming language has become increasingly popular in the world of web development. If you have prior experience with Python or similar languages, it won't take long until you grasp the basics of Ruby. When you look at Ruby from a PHP background, there might be some surprises up ahead - but for me, they were mostly pleasant surprises. This tutorial is meant to introduce some basic Ruby concepts. After going through this, you will be able to look at simple Ruby code without headaches, and have a better understanding of some of the R

Getting Ruby up and running


Before we start analysing the language, we'll cover the easy installation of Ruby. As a Windows user (like me), you just have to visit the Ruby website and download the one-click installer. The installation process for other operating systems is explained on the same page. I'll be using the Interactive Ruby Shell, irb, throughout this tutorial. On Windows, when the installer has finished, it will ask you whether to add Ruby to the PATH, and whether to associate .rb files with Ruby. It's probably best to select both checkboxes. Next, you'll need to fire up your console by typing "cmd" in the "execute" field, accessible using the start menu. Vista and Windows 7 users can also launch the console from within a directory, by shift + right-clicking in explorer. In order to launch irb, just type "irb" in the console window. To use irb, just type in some Ruby code and press enter. The system will then evaluate the expression, and present the result. For example, if you type "Hello World!", irb will respond by saying "Hello World!". Okay, now that Ruby has been installed, let's took a look at the language itself. For more info on irb, I suggest this link.




Instead of using irb, you can also create source files and execute those. A Ruby source file has the .rb extension, and simply contains Ruby code. You can launch it from the command line using the Ruby command (on Windows, it might work slightly different/easier on other operating systems). For example, you could create a test.rb source file containing the following code:


def foo()
return 5
end

def bar()
return foo + 3
end

puts bar()


And then run it from the console:


 

 



The main difference with PHP: OO-ness


The first thing that comes to mind when people think about Ruby, is that it's a full-fledged Object Oriented language. PHP, on the other hand, is an imperative language which turned hybrid later on. You basically have variables which point to data such as strings and integers, and functions which act on this data. In later versions of PHP, you are able to define classes that act as blueprints for objects. These objects contain some encapsulated data, which you can access using methods. Now, enter the world of Ruby: everything is an object. Try the following expressions in irb:


[5,4,3,2,1].length
"54321".length
(8-12).abs
5.class
5.2.class
(5.2-5.0).abs.class


Maybe these expressions will look surprising, but the results probably won't. Ruby tends to do what you expect it to do. Your surprises will often be "Hey, this works!"-surprises, as opposed to the "Hey, why doesn't this work?"-surprises that some other programming languages offer you. As you can see, these expressions also have a clean syntax without lots of silly parentheses. In fact, you can add parentheses to the end of the method calls, but they are usually dropped, unless they are necessary for readability. So, I suppose I have convinced you of Ruby's Object Orientedness now. I will not go into depth on the Object Oriented facilities of Ruby in this tutorial, but Ruby offers everything you would expect from it: access control, inheritance and polymorphism (or the ability to act polymorphic, the name is debatable). For now, there are lots of other things to introduce.

 


"Everything in Ruby is an object, even the built-in types."


 

 



The Ruby language

 

 

Syntactical differences with PHP


The obvious difference in syntax between PHP and Ruby is in the use of parentheses. PHP uses a lot of them, Ruby uses as few as possible. Semicolons aren't used either. Unlike Python, though, indentation isn't important in Ruby (but the Ruby community prefers two-space indentation). Most constructs start with "begin" and end with an "end" keyword. Secondly, Ruby doesn't use dollarsigns for its (normal) variables. A variable is just a word, an instance variable is prefixed with an @ and a class variable is prefixed with @@. The dollarsign is used to create global variables. Here's an example to illustrate the syntactic differences:


function foo($bar){
if ($bar > 5){
$bar++;
return $bar - 5;
}
else{
$bar--;
return $bar + 5;
}
}

def foo(bar)
if bar > 5
bar += 1
return bar - 5
else
bar -= 1
return bar + 5
end
end

 

 

Controlling program flow

As we've seen in the above example, Ruby's if-construct is basically the same as PHP's. There is also a case, which matches PHP's switch. You may expect Ruby to offer the same looping constructs as other programming languages, but here's a surprise. The common while and until loops are present, but the traditional for loop (start, condition, change) isn't. There is a rather foreach-like "for x in y" loop, though. In addition, Ruby uses iterators which allow you to simulate a loop through a method call. I may have told you once before that everything in Ruby was Object Oriented ... So, if we wish to do something for a variable from 1 to 5, we could type 'for x in (1..5)'. Or we could use the upto method of our Fixnum class, and pass it a code block. The following snippets both print the numbers from 1 up to 5:


for x in (1..5)
puts x
end

1.upto(5) {|i| puts i}

I'll explain a little bit more about iterators later on in this tutorial. Some of you may have noticed that Ruby's printing command, puts, doesn't look like a method call. Again, I won't go into depth on this subject, but puts is a method call. You can think of it as being executed in the context of some "super object" that contains your top-level code.

Having a clean and legible syntax is obviously one of Ruby's goals. Some flow control constructs therefore have an alternative form, which sounds a little more intuitive. Which one you ultimately choose, is up to you. For example, these expressions have the same result:


if i != 0
return i

return i unless i == 0

return i if i != 0


"Ruby features most of the usual control structures, except the PHP-style for loop. This can easily be simulated using Ruby's iterators."


 

 

Arrays, hashes and symbols

Before we move on to a thorough explanation of iterators, it's preferable to talk about some objects you'll often iterate through. First, we'll introduce the Range. A Range is basically ... well, a range. There's no better way to explain it. Ranges are of the form (x...y), where x is the begin and y is the end of the range. Two dots indicate that y is included in the range, three dots exclude y. In the following example, I used the each iterator to print all the values in the range:



Ranges may be useful, but if you're developing for the web, you'll spend more time using arrays and hashes. They are quite similar to PHP's arrays and associative arrays:



There is a big difference though, in the way you can index and assign to arrays. You can get a slice of the array by indexing using a Range or giving a starting index and a length. You can also assign to slices of the array. And you can use negative indexes to start counting from the back, though Ruby won't consider the array to be "circular" - if you ask for two elements, starting from the last one, you won't get the last and the first. Again, none of the expressions yields a result you wouldn't expect.



The next object type is the Symbol, which is frequently used in Ruby on Rails, for example. Symbols look like strings without quotation marks, prefixed with a colon. Ruby programmers will usually use Symbols to index hashes, instead of strings. The main difference is a question of memory management. When you introduce a string, it gets a place on your memory heap. When you introduce another one, it gets its own place, regardless of whether the contents are the same. After all, when you change the string "Hello" into "World", you don't want all "Hello"s in your program to change along. When you use Symbols, they will correspond to the same memory object - when they match, that is. This makes them ideal for indexing hashes.



So in the following example, there will be two strings "Foo" in the memory, and just one Symbol :bar


a = {:bar => 1, "Foo" => 2}
b = {:bar => 2, "Foo" => 1}

 

 

Iterators

So, we've finally arrived to the subject of iterators. As the name indicates, iterators will be used to traverse sequences, and operate on them. They are basically functions which take a code block as an argument, and invoke this block on all or certain elements in a sequence. In the previous sections, we have already used iterators to simulate an integral for loop. Iterators are more powerful, though. Assume we want to do something with fibonacci numbers only. We can create an iterator each_fib, that selects the fibonacci numbers in a sequence (anything that supports the each method) and passes them to a code block. This is done using yield. Note that you can pass multiple arguments, like we've done for the hashes.


def each_fib(numbers)
numbers.each do |i|
if is_fib(i) then
yield i
end
end
end

The is_fib check is implemented using a method I found on wikipedia:


def is_fib(z)
return is_integral(Math.sqrt((5*z*z) + 4)) || is_integral(Math.sqrt((5*z*z) - 4))
end

 

def is_integral(x)
return x == x.round
end

So now, let's put this iterator to use, and let it print out all the fibonacci numbers in a given array:

nums = [1,4,8,12,16,20,21,22]
each_fib(nums) {|i| puts i}


It works like a charm! So, whenever we need to do something with all the fibonacci numbers in a sequence (which, sadly, doesn't occur too often), we can use this iterator. This is basically how every iterator works, though you can use them for more complicated tasks. Now, you could implement this in PHP by passing functions, like array_walk(), for example. The main difference is a matter of elegance. Ruby doesn't force you to create a standalone function, whereas PHP requires an explicitly declared callback function. As usual in programming, it's debatable whether the Ruby approach is that much better. To me, it's just another case where Ruby just allows you to write better-looking and more legible code, in contrast to PHP.

To conclude with, here are some iterators you might use quite ofte

  • each

    Yields every element in the sequence

    Usage: [1,2,3].each {|i| puts i}

  • collect

    Yields every element in the sequence, and stores the return value of your block, e.g. if you want to uppercase every string instead of just printing it.

    Usage: [1,2,3].collect {|i| i*2}

  • times

    Iterator for numbers, which allows you to repeat something multiple times.

    Usage: 5.times {puts "Hello"}

  • inject

    Yields every element in the sequence, along with the result of the previous call as the first parameter. Can be used to sum the elements of an array, for instance.

    Usage: [1,2,3].inject {|x,y| x+y}

 

 



Concluding this tutorial

 

 

Tips & Tricks

  • Ruby method names can contain punctuation, allowing names such as "is_empty?" or "destroy!".

  • Ruby uses reference assignment by default.

  • You can turn various objects into a string by using the "to_s" method.

  • Ruby method arguments can have default values in the same way as PHP functions.

  • You can ommit the return keyword in functions. Ruby will then return the result of the last expression.

 

 

Ten things that weren't covered

The following subjects weren't touched in this tutorial, because I don't consider them "basic". These aren't all the remaining interesting subjects of Ruby, just a list of some that I know about, and that can be useful for webdevelopers. You can find more information about them on the internet, or wait for an intermediate Ruby tutorial to appear:

  • Defining classes and creating objects

  • Inheritance & Mixins

  • Duck Typing

  • Modules

  • Reflection

  • Regular Expressions

  • File Handling

  • Database Handling

  • Exceptions

  • Ruby's Unittesting facilities

 

 

Further reading

If you are interested in the Ruby programming language and wish to read more about it, you can check out the links on the Ruby website's documentation page. I would especially recommend the Pragmatic Programmers' Ruby book, also know as the Pickaxe. There is a free version available on the Ruby website.

 

What did you think of this tutorial?
+ 2
0 CommentsAdd a Comment
Name
Comment