Ruby para programadores PHP
Leia em 8 minutos
A maneira mais fácil de se aprender uma nova linguagem é comparando-a com uma linguagem que você já conhece. Pelo menos é assim que faço! Para os que são como eu, aqui vai uma série de comparações/equivalências entre as linguagens Ruby e PHP.
Estruturas de controle
Condicionais
# php
# setting some variables
$n1 = 1;
$n2 = 2;
$n3 = 3;
# if condition
if ($n1 > $n2)
echo 'n1 > n2',"\n";
elseif ($n1 > $n3)
echo 'n1 > n3', "\n";
else
echo 'n1 =< n2; n1 =< n3', "\n";
# one-line if
echo n3 > n2? "n3 > n2\n" : "n3 <= n2\n";
# switch..case
switch($n1) {
case 1:
echo "n1 = 1", "\n";
break;
case 2:
echo "n1 = 2", "\n";
break;
default:
echo "n1 = {$n1}", "\n";
}
# ruby
# setting some variables
n1 = 1
n2 = 2
n3 = 3
# if condition
if n1 > n2
puts 'n1 > n2'
elsif n1 > n3
puts 'n1 > n3'
else
puts 'n1 =< n2; n1 =< n3'
end
# one-line if
puts n3 > n2 ? 'n3 > n2' : 'n3 <= n2'
# unless condition
unless n3 > n2
puts 'n3 > n2'
end
# different structure
puts 'n1 > n3' if n1 > n3
puts 'n1 =< n2' unless n1 > n2
# switch..case
case n1
when 1
puts 'n1 = 1'
when 2
puts 'n1 = 2'
else
puts 'n1 = %d' % n1
end
Estruturas de repetição
# php
# while
$i = 1;
while ($i < 5) {
echo $i, "\n";
$i += 1;
}
# do..while
$i = 1;
do {
echo $i, "\n";
$i += 1;
} while ($i < 5);
# for i++
for ($i = 1; $i <= 5; $i++) {
echo $i, "\n";
}
# for i--
for ($i = 5; $i >= 1; $i--) {
echo $i, "\n";
}
# each
foreach (range(1,5) as $i) {
echo $i, "\n";
}
# break/continue
$i = 0;
while ($i < 10) {
$i++;
# break
if ($i == 9) {
break;
}
# continue
if ($i % 2 == 0) {
continue;
}
echo $i, "\n";
}
# ruby
# while
i = 1
while i < 5
puts i
i += 1
end
# until
i = 1
until i > 5
puts i
i += 1
end
# loop
i = 1
loop do
break if i > 5
puts i
i += 1
end
# do..while
i = 1
begin
puts i
i += 1
end while i < 5
# do..until
i = 1
begin
puts i
i += 1
end until i > 5
# upto (for i++)
1.upto(5) do |i|
puts i
end
# downto (for i--)
5.downto(1) do |i|
puts i
end
# for..in (foreach)
for i in (1..5)
puts i
end
# each
(1..5).each do |i|
puts i
end
# break/next
i = 0
while i < 10 do
i += 1
break if i == 9 # break
next if i % 2 == 0 # next (continue)
puts i
end
Strings
Particularmente, penso que o PHP é muito mais completo para se lidar com strings quando o assunto é biblioteca padrão. Na maioria das vezes você possui alternativas — estender a classe, por exemplo — mas é um trabalho que alguém terá que fazer.
Manipulando strings
# php
# interpolate variables
$text = "php";
echo "i love $text", "\n";
echo "i love {$text}", "\n";
printf("i love %s\n", $text);
# basic functions
$text = 'i love php';
echo strtolower('I LOVE PHP'), "\n"; # lowercase text
echo strtoupper($text), "\n"; # uppercase text
echo ucfirst($text), "\n"; # capitalize text
echo strlen($text), "\n"; # string size
echo strrev($text), "\n"; # reversing text
echo str_repeat("php ", 3), "\n"; # repeat text
echo ord("a"), "\n"; # get ASCII value
echo chr("97"), "\n"; # get char from ASCII value
# remove spaces
$text = ' i love php ';
echo trim($text), "\n"; # both sides
echo ltrim($text), "\n"; # just left side
echo rtrim($text), "\n"; # just right side
# remove characters
$text = '__i love php__';
echo trim($text, '_'), "\n"; # both sides
echo ltrim($text, '_'), "\n"; # just left side
echo rtrim($text, '_'), "\n"; # just right side
# slicing strings
$text = 'i love php';
echo substr($text, 0, 6), "\n";
echo $text[0], "\n";
# search characters
echo strpos("php", "h"), "\n"; # find position
# ruby
# interpolate variables
text = "ruby"
puts "i love #{text}";
puts "i love %s" % text;
printf("i love %s\n", text);
# basic functions
text = 'i love ruby';
puts 'I LOVE RUBY'.downcase # lowercase text
puts text.upcase # uppercase text
puts text.capitalize # capitalize text
puts text.size # string size
puts text.reverse # reversing text
puts "ruby " * 3 # repeat text
puts "a"[0] # get ASCII value
puts 97.chr # get char from ASCII value
# remove spaces
text = ' i love ruby ';
puts text.strip # both sides
puts text.lstrip # just left side
puts text.rstrip # just right side
# remove characters
# ruby has no easy way of doing that besides regular expressions
# so we're gonna extend String class
# check this link out: http://nandovieira.com.br/
text = '||__i love ruby__||'
puts text.trim('_|') # both sides
puts text.ltrim('_|') # just left side
puts text.rtrim('_|') # just right side
# slicing strings
text = 'i love ruby';
puts text[0,6]
puts text[0,1]
# search characters
puts "ruby" =~ /y/ # find position
Gerando hashes com MD5 e SHA1
# php
echo md5("php"), "\n";
echo sha1("php");
# ruby
require 'digest/md5'
require 'digest/sha1'
puts Digest::MD5.hexdigest("ruby")
puts Digest::SHA1.hexdigest("ruby")
Expressões regulares
No PHP temos uma série de funções que lidam com expressões regulares como eregi
, preg_match
, preg_replace
, dentre outras. O Ruby também tem métodos equivalentes:
preg_match vs match
Verificar se uma determinada string obedece um padrão
#php
if(preg_match("/^\d{2}\/\d{2}\/\d{4}$/", '01/01/2007')) {
print 'valid format'
} else {
print 'invalid format'
}
# ruby - method 1
if '01/01/2007' =~ /^\d{2}\/\d{2}\/\d{4}$/
puts 'valid format'
else
puts 'invalid format'
end
# ruby - method 2
if '01/01/2007'.match(/^\d{2}\/\d{2}\/\d{4}$/)
puts 'valid format'
else
puts 'invalid format'
end
Acessando os matches de uma expressão regular
# php
preg_match("/like/", "i like php", $matches);
print "match: " . $matches[0];
# ruby
matches = "i like ruby".match(/like/)
puts matches[0]
Atribuindo os matches de uma expressão regular à variáveis
# php
preg_match("/(\b\w+\b) (\b\w+\b)/", "nando vieira", $matches);
list($full_name, $first_name, $last_name) = $matches;
print $full_name . "\n";
print $first_name . "\n";
print $last_name;
# ruby
full_name, first_name, last_name = *"nando vieira".match(/(\b\w+\b) (\b\w+\b)/)
puts full_name
puts first_name
puts last_name
preg_replace vs gsub
Substituíndo padrões
# php
print preg_replace("/like/", "love", "i like php")
# ruby
puts "i like ruby".gsub(/like/, 'love')
Utilizando retrovisores (backreferences)
# php
print preg_replace("/(duck)/", "\$1 and one chicken", "one duck")
# ruby
puts "one duck".gsub(/(duck)/, "\1 and one chicken")
preg_match_all vs scan
# php
$text = "item 1\nitem 2\nitem 3";
preg_match_all("/item (\d+)/sim", $text, $matches);
print_r($matches[1]);
# ruby
text = "item 1\nitem 2\nitem 3"
matches = text.scan(/item (\d+)/)
puts matches
Array e Hash
Utilizando arrays
# php
$companies = array('apple', 'microsoft', 'red hat', 'canonical');
echo count($companies), "\n"; # how many items?
echo $companies[0], "\n"; # first item
echo end($companies), "\n"; # last item
echo (int)empty($companies), "\n"; # size > 0?
# sorting array
sort($companies);
# removing duplicate items
$companies = array_unique($companies);
# applying a function
$companies = array_map('strtoupper', $companies);
# reversing
$companies = array_reverse($companies);
# joining
echo join(", ", $companies), "\n";
# slicing
echo join(", ", array_slice($companies, 1, 3)), "\n";
# removing last item
echo array_pop($companies), "\n";
# removing first item
echo array_shift($companies), "\n";
# adding item at the end
array_push($companies, 'ADOBE');
# adding item at the beginning
array_unshift($companies, 'NOVELL');
# ruby
companies = ['apple', 'microsoft', 'red hat', 'canonical']
puts companies.size # how many items?
puts companies.first # first item
puts companies.last # last item
puts companies.empty? # size > 0?
# sorting array
companies.sort!
# removing duplicate items
companies.uniq!
# applying a function
companies.map! { |company| company.upcase }
# reversing
companies.reverse!
# joining
puts companies.join(", ")
# slicing
puts companies[1..3].join(", ")
puts companies.slice(1, 3).join(", ")
# removing last item
puts companies.pop
# removing first item
puts companies.shift
# adding item at the end
companies.push 'ADOBE'
# adding item at the beginning
companies.unshift 'NOVELL'
Arrays associativos
No Ruby, os arrays associativos são definidos como Hash e tem sua sintaxe ligeiramente diferente. Vale lembrar que, ao iterar um hash, os valores apresentados geralmente não os mesmos da ordem de inserção.
# php
$companies = array(
'apple' => 'mac os x',
'microsoft' => 'windows vista',
'canonical' => 'ubuntu'
);
echo $companies['apple'], "\n";
# getting the keys
echo join(", ", array_keys($companies)), "\n";
# iterating through array
foreach ($companies as $company => $so) {
printf("%s: %s\n", $company, $so);
}
# removing a item
unset($companies['microsoft']);
# checking if array has a key
if (!array_key_exists('novell', $companies)) {
echo "Novell not found\n";
}
# ruby
companies = {
'apple' => 'mac os x',
'microsoft' => 'windows vista',
'canonical' => 'ubuntu'
}
puts companies['apple']
# getting the keys
puts companies.keys.join(", ")
# iterating through array
companies.each do |company, so|
puts "%s: %s" % [company, so]
end
# removing a item
companies.delete('microsoft')
# checking if array has a key
puts 'Novell not found' if not companies.key?('novell')
Arquivos e diretórios
Arquivos
Criar novo novo arquivo e adicionar conteúdo
# php
$file = fopen('newfile.txt', 'w+');
fwrite($file, str_repeat("i love php\n", 10));
fclose($file);
# ruby
file = File.new('newfile.txt', 'w+')
file << "i love ruby\n" * 10
file.close
Lendo arquivos
# php
$file = fopen('newfile.txt', 'r');
echo fwrite($file, ('newfile.txt')), "\n";
fclose($file);
# ruby
file = File.new('newfile.txt')
puts file.read
file.close
Iterando nas linhas do arquivo
# php
$lines = file('newfile.txt');
foreach ($lines as $num => $line) {
echo $num+1, ': ', $line;
}
# ruby
file = File.new('newfile.txt')
file.each_with_index do |line, num|
puts "%d: %s" % [num+1, line]
end
file.close
Outras funções
# php
# check if file exists
echo (int)file_exists('newfile.txt'), "\n";
# print file size in bytes
echo filesize('newfile.txt'), "\n";
# write permission?
echo (int)is_writable('newfile.txt'), "\n";
# read permission?
echo (int)is_readable('newfile.txt'), "\n";
# is file?
echo (int)is_file('newfile.txt'), "\n";
# remove file
unlink('newfile.txt');
# ruby
# check if file exists
puts File.exists?('newfile.txt')
# print file size in bytes
puts File.size('newfile.txt')
# write permission?
puts File.writable?('newfile.txt')
# read permission?
puts File.readable?('newfile.txt')
# is file?
puts File.file?('newfile.txt')
# remove file
File.unlink('newfile.txt')
Diretórios
# php
# creating new directory
mkdir('newdir');
# listing files
$dir = opendir("newdir");
while (false !== ($entry = readdir($dir))) {
echo $entry, "\n";
}
closedir($dir);
# directory?
echo (int)is_dir('newdir'), "\n";
# remove non-empty directory
# php have no such function
# check this link out for alternatives
# http://php.net/rmdir
# remove empty directory
rmdir('newdir');
# ruby
# creating new directory
dir = Dir.mkdir('newdir')
file = File.new('newdir/newfile.txt', 'w+')
# listing files
dir = Dir.new('newdir')
dir.entries.each do |entry|
puts entry
end
# directory?
puts File.directory?('newdir')
# remove non-empty directory
require 'fileutils'
FileUtils.rm_rf('newdir')
# remove empty directory
Dir.mkdir('newdir')
Dir.rmdir('newdir')
Classes
# php
class Vehicle {
# read/write attribute
public $name;
# private attribute
private $color;
# constructor
function __construct($name)
{
$this->name = $name;
}
# setter
function setColor($colorName)
{
$this->color = $colorName;
}
# getter
function getColor()
{
return $this->color;
}
# static
function getWheels()
{
return 0;
}
}
class Car extends Vehicle {
function __construct($name)
{
parent::__construct($name);
}
function getWheels()
{
return 4;
}
}
$car = new Car('Stilo');
echo $car->name, "\n"; # name attribute
echo get_class($car), "\n"; # object class
$car->setColor('graffiti');
echo $car->getColor(), "\n";
echo Car::getWheels(), "\n"; # static method
# ruby
class Vehicle
# read/write attribute
attr_accessor :name
# class variable
@@wheels = 0
# contructor
def initialize(name)
@name = name
end
# color getter
def color
@color
end
# color setter
def color=(color_name)
@color = color_name
end
def self.wheels
@@wheels
end
end
class Car < Vehicle
@@wheels = 4
def initialize(name)
super(name)
end
end
car = Car.new('Stilo')
puts car.name # name attribute
puts car.class # object class
car.color = 'yellow'
puts car.color
puts Car::wheels # class method (static method on PHP)
Lendo páginas da web (scraping)
Processando XML
# php
$curl = curl_init('http://del.icio.us/rss/fnando');
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($curl);
$xml = new SimpleXMLElement($response);
foreach ($xml->item as $item) {
$title = $item->title;
$link = $item->link;
printf("%s\n%s\n\n", $title, $link);
}
# ruby
require 'net/http'
require 'uri'
require 'rexml/document'
url = URI.parse('http://del.icio.us/rss/fnando')
response = Net::HTTP.get(url)
xml = REXML::Document.new(response)
xml.root.elements.to_a('//item').each do |item|
title = item.elements['title'].text
link = item.elements['link'].text
puts "%s\n%s\n\n" % [title, link]
end
Processando HTML
# php
$curl = curl_init('http://www.google.com/trends/music');
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($curl);
preg_match_all("/<a.*?href=\".*?&res=artist.*?>(.*?)<\/a>/sim", $response, $matches);
echo join("\n", array_unique($matches[1])), "\n";
require 'net/http'
require 'uri'
require 'rexml/document'
url = URI.parse('http://www.google.com/trends/music')
response = Net::HTTP.get(url)
regex = /<a.*?href=".*?&res=artist.*?>(.*?)<\/a>/sim
puts response.scan(regex).uniq.join("\n")
Se você acha que eu deveria ter abordado algum outro conjunto de funções, avise-me e atualizarei o artigo. Divirta-se!
Update: Adicionei estruturas de controle