Aprenda Ruby em Vinte Minutos

Este é um pequeno tutorial de Ruby que não deverá demorar mais de 20 minutos a completar. Assume-se á partida que já tem o Ruby instalado.

Por | @oficinadanet Programação

Este é um pequeno tutorial de Ruby que não deverá demorar mais de 20 minutos a completar. Assume-se á partida que já tem o Ruby instalado. (Se não tem o Ruby no seu computador, faça o download e instale-o antes de começar.)

Ruby Interativo


Abrir o IRB.
  • Se está a usar Mac OS X abra o Terminal, escreva irb, e depois pressione a tecla enter.
  • Se está a usar Linux, abra uma shell e escreva irb, seguido de enter.
  • Se está a usar Windows, abra fxri a partir do atalho para o Ruby no seu menu Iniciar.

irb(main):001:0>

Ok, abriu. E agora?
Escreva isto: "Ola Mundo"
irb(main):001:0> "Ola Mundo"
=> "Ola Mundo"

O Ruby obedeceu-lhe!


O que é que sucedeu? Será que acabamos de escrever o mais pequeno programa «Olá mundo»? Não exatamente, a segunda linha é a forma de o IRB nos dizer qual o resultado da última expressão que avaliou. Se desejarmos imprimir «Ola Mundo» necessitamos de um pouco mais:
irb(main):002:0> puts "Ola Mundo" 
Ola Mundo 
=> nil

puts é o comando básico para imprimir algo em Ruby. Mas então o que é aquele => nil ? É o resultado da expressão. puts retorna sempre nil, o que em Ruby é o valor que representa o nada absoluto.

Uma Máquina Calculadora gratuita


Já temos neste momento conhecimento suficiente para utilizar o IRB como uma calculadora básica:
irb(main):003:0> 3 2
=> 5

Três mais dois. Suficientemente fácil. E então três vezes dois? Pode escrevê-lo, é suficientemente curto, mas também podemos voltar atrás e mudar o que acabamos de inserir. Carregue na tecla Seta para cima do teclado e veja se tal o leva à linha com 3 2. Se tal suceder, use a tecla da seta para a esquerda para mover o cursor para a frente do sinal de mais e depois use a tecla de backspace para mudar o sinal para *.
irb(main):004:0> 3*2
=> 6

De seguida vamos tentar três ao quadrado:
irb(main):005:0> 3**2
=> 9

Em Ruby ** é a forma de dizer potência de. Mas o que acontece quando queremos saber o inverso disto ou seja a raiz quadrada de algo?
irb(main):006:0> Math.sqrt(9)
=> 3.0

Muito bem, o que aconteceu aqui atrás? Se disse ?que estava a determinar a raiz quadrada de nove? então está correcto. Mas vejamos as coisas com mais pormenor. Primeiro de tudo, o que é Math?

Módulos, Agrupar Código por Tópico


Math é um módulo nativo para funções matemáticas. Os módulos têm dois papeis em Ruby. Este é um desses papeis: agrupar métodos semelhantes em conjunto sobre um nome familiar. Math também contém métodos como sin() e tan().

Depois segue-se um ponto final. O que faz o ponto? O ponto final é como se identifica o receptor de uma mensagem. Qual é a mensagem? Neste caso é sqrt(9), o que significa chamar o método sqrt, uma abreviatura em língua inglesa para ?square root (raiz quadrada)? com o parâmetro 9.

O resultado desta chamada de método é o valor 3.0. Se repararmos bem, o resultado não é apenas 3. Mas isso deve-se ao facto da raiz quadrada de um número na maioria dos casos não ser um inteiro e, assim sendo, o método retorna sempre um número de vírgula flutuante.

E se nos quisermos lembrar do resultado desta matemática toda? Podemos atribuir o resultado a uma variável.
irb(main):007:0> a = 3 ** 2
=> 9
irb(main):008:0> b = 4 ** 2
=> 16
irb(main):009:0> Math.sqrt(a b)
=> 5.0

Como calculadora isto é muito bom mas nós estamos a afastarmos-nos da mensagem mais tradicional Ola Mundo que os guias de iniciação normalmente focam.

[PG1]

E se quisermos dizer "Olá" varias vezes sem cansar os dedos? Temos que definir um método!
irb(main):010:0> def h
irb(main):011:1> puts "Olá Mundo!"
irb(main):012:1> end
=> nil

O código def h começa a definição do método. Diz ao Ruby que estamos a definir um método, cujo nome é h. A linha seguinte é o corpo do método, a mesma frase que vimos antes: puts "Olá Mundo". Finalmente, a última linha end diz ao Ruby que terminámos a definição do método. A resposta do Ruby => nil diz-nos que sabe que terminamos a definição do método.

As Breves e Repetitivas Vidas de um Método


Agora tentemos correr o método algumas vezes:
irb(main):013:0> h
Olá Mundo!
=> nil
irb(main):014:0> h()
Olá Mundo!
=> nil

Bem, esta foi fácil. Chamar um método em Ruby é tão fácil como mencionar o seu nome ao Ruby. Se o método não tiver parâmetros é tudo o que precisamos. Podemos também colocar os parênteses vazios se desejar-mos, porem estes não são necessários.

E se o que queremos é dizer ola a uma pessoa só, e não ao mundo inteiro? Para isso basta redifinir h para que aceite um nome como parâmetro.
irb(main):015:0> def h(nome)
irb(main):016:1> puts "Olá #{nome}!"
irb(main):017:1> end
=> nil
irb(main):018:0> h("Matz")
Olá Matz!
=> nil

Parece funcionar? mas vamos pausar um minuto para ver o que se passa aqui.

Reservando espaços numa String


O que significa a expressão @#{nome}? É a forma de inserir alguma coisa numa string. Aquilo que se encontra entre chavetas transforma-se numa string (se já não o for) e é substituído naquele ponto da string. Podemos também usar isto para ter a certeza de que o nome de alguém se apresenta em letra maiúscula:
irb(main):019:0> def h(nome = "Mundo")
irb(main):020:1> puts "Olá #{nome.capitalize}!"
irb(main):021:1> end
=> nil
irb(main):022:0> h "chris"
Olá Chris!
=> nil
irb(main):023:0> h
Olá Mundo!
=> nil

Podemos encontrar aqui um truque ou dois. Um deles é que estamos a chamar novamente o método sem recorrer aos parênteses. Se aquilo que estamos a fazer for óbvio então os parênteses são opcionais. O outro truque é o parâmetro Mundo usado por omissão. O que isto quer dizer é que? Se o nome não for fornecido, então usamos o nome por omissão "Mundo".
Evoluindo para um Anfitrião

E se quisermos criar um Anfitrião mais "sério"? Um que se lembre do nosso nome, nos dê as boas vindas e nos trate com o respeio devido? Podemos usar um objecto para esse efeito. Vamos então criar, a classe "Anfitrião".
irb(main):024:0> class Anfitriao
irb(main):025:1>   def initialize(nome = "Mundo")
irb(main):026:2>     @nome = nome
irb(main):027:2>   end
irb(main):028:1>   def diz_ola
irb(main):029:2>     puts "Olá #{@nome}!"
irb(main):030:2>   end
irb(main):031:1>   def diz_adeus
irb(main):032:2>     puts "Adeus #{@nome}, volte sempre."
irb(main):033:2>   end
irb(main):034:1> end
=> nil

A nova palavra chave aqui é class. Esta define uma nova classe chamada Anfitrião e uma quantidade de métodos para essa classe. E o @nome ? É uma variável de instância e está disponível para todos os métodos da classe. Como podemos ver está a ser utilizada por diz_ola e diz_adeus.

Então como é que pomos a classe Anfitrião em movimento?

[PG2]

Agora vamos criar e usar um objecto Anfitrião:
irb(main):035:0> h = Anfitriao.new("João")
=> #
irb(main):036:0> h.dizer_ola
Ola João
=> nil
irb(main):037:0> h.dizer_adeus
Adeus João, volta em breve.
=> nil

Uma vez criado o objecto h, lembra-nos que o nome é João. Mmm, e se quisermos aceder diretamente ao nome?
irb(main):038:0> h.@nome
SyntaxError: compile error
(irb):52: syntax error
        from (irb):52

Não o podemos fazer.

Por baixo da pele do objecto


As variáveis de instância escondem-se dentro do objecto. Não estão assim tão bem escondidas, podem ser vistas quando se inspecciona o objecto e há outras formas de lhes aceder, mas Ruby é fiel aos bons costumes da programação orientada a objectos mantendo os dados o mais privados possíveis.

Então, que métodos estão disponíveis para os objectos Anfitrião?
irb(main):039:0> Anfitriao.instance_methods
=> ["method", "send", "object_id", "singleton_methods",
    "__send__", "equal?", "taint", "frozen?",
    "instance_variable_get", "kind_of?", "to_a",
    "instance_eval", "type", "protected_methods", "extend",
    "eql?", "display", "instance_variable_set", "hash",
    "is_a?", "to_s", "class", "tainted?", "private_methods",
    "untaint", "decir_hola", "id", "inspect", "==", "===",
    "clone", "public_methods", "respond_to?", "freeze",
    "decir_adios", "__id__", "=~", "methods", "nil?", "dup",
    "instance_variables", "instance_of?"]

Bem. São muitos métodos. Nós só definimos dois métodos. O que é que aconteceu? Bem estes são todos os métodos para os objectos Anfitrião, uma lista completa, incluindo os que estão definidos nas super-classes de Anfitrião. Se só quisermos listar unicamente os métodos definidos para a classe Anfitrião, podemos pedir-lhe que não inclua os métodos dos seus ancestrais passando-lhe o parâmetro false, que significa que não queremos os métodos definidos pelos seus ancestrais.
irb(main):040:0> Anfitriao.instance_methods(false)
=> ["dizer_adeus", "dizer_ola""]

Há mais coisas a explorar. Vejamos a que métodos pode responder o nosso objecto Anfitrião:
irb(main):041:0> h.respond_to?("nome")
=> false
irb(main):042:0> h.respond_to?("dirzer_ola")
=> true
irb(main):043:0> h.respond_to?("to_s")
=> true

Assim ficamos a saber que responde a dizer_ola, e to_s (que significa "converter algo numa string", um método que está definido por omissão para todos os objectos), mas que não reconhece nome como método.

Modificar classes - Nunca é demasiado tarde


E se quiser alterar o nome? Ruby oferece uma forma fácil de lhe permitir o acesso às variáveis de um objecto.
irb(main):044:0> class Anfitriao
irb(main):045:1>   attr_accessor :nome
irb(main):046:1> end
=> nil

Em Ruby, podemos voltar a abrir e alterar uma classe. Isso não altera os objectos já existentes, mas afecta os novos objectos que se possam criar. Assim vamos criar um novo objecto e vamos brincar com a sua propriedade @nome.
irb(main):047:0> h = Anfitriao.new("Pedro")
=> #
irb(main):048:0> h.respond_to?("nome")
=> true
irb(main):049:0> h.respond_to?("nome=")
=> true
irb(main):050:0> h.dizer_ola
Ola Pedro
=> nil
irb(main):051:0> h.nome="Matilde"
=> "Matilde"
irb(main):052:0> h
=> #
irb(main):053:0> h.nome
=> "Matilde"
irb(main):054:0> h.dizer_ola
Ola Matilde
=> nil

O uso de attr_accessor determina que se tenha definido dois novos métodos: nome para obter o valor, e nome= para o alterar.

Saudar todos, MegaAnfitriao não nega a saudação a ninguém!


De qualquer modo este Anfitrião não é assim tão interessante, só pode trabalhar para uma pessoa de cada vez. O que se passaria se tivéssemos uma classe MegaAnfitriao que pudesse saudar o mundo inteiro, uma pessoa ou uma lista completa de pessoas?

Vamos escrever isto num ficheiro em vez de usar directamente o interpretador interactivo do Ruby (IRB).

Para sair do IRB, escrevemos "quit", "exit" ou simplesmente carregamos nas teclas "Control" e "D".
#!/usr/bin/env ruby

class MegaAnfitriao
  attr_accessor :nomes

  # Criar o objecto
  def initialize(nomes = "Mundo")
    @nomes = nomes
  end

  # Dizer ola a todos
  def dizer_ola
    if @nomes.nil?
      puts "..."
    elsif @nomes.respond_to?("each")

      # @nomes é uma lista de algum tipo,
      # assim podemos iterar!
      @nomes.each do |nome|
        puts "Ola #{nome}"
      end
    else
      puts "Ola #{@nomes}"
    end
  end

  # Dizer adeus a todos
  def dizer_adeus
    if @nomes.nil?
      puts "..."
    elsif @nomes.respond_to?("join")
      # Juntar os elementos à lista
      # usando a vírgula como separador
      puts "Adeus #{@nomes.join(", ")}. Voltem em breve."
    else
      puts "Adeus #{@nomes}. Volta em breve."
    end
  end

end


if __FILE__ == $0
  mh = MegaAnfitriao.new
  mh.dizer_ola
  mh.dizer_adeus

  # Alterar o nome para "Diogo"
  mh.nomes = "Diogo"
  mh.dizer_ola
  mh.dizer_ola

  # Alterar o nome para um vector de nomes
  mh.nomes = ["Alberto", "Beatriz", "Carlos",
    "David", "Ernesto"]
  mh.dizer_ola
  mh.dizer_adeus

  # Alterar para nil
  mh.nomes = nil
  mh.dizer_ola
  mh.dizer_adeus
end

Guardar este ficheiro como ri20min.rb, e executar com o comando ruby ri20min.rb. O resultado deverá ser:
Ola Mundo
Adeus Mundo. Volta em breve.
Ola Diogo
Adeus Diogo. Volta em breve.
Ola Alberto
Ola Beatriz
Ola Carlos
Ola David
Ola Ernesto
Adeus Alberto, Beatriz, Carlos, David, Ernesto.
Voltem em breve.
...
...


[PG3]

Vejamos então o nosso novo programa de modo mais aprofundado, de notar que as linhas iniciais começam com um sinal de cardinal(#). Em Ruby, algo após um sinal de cardinal é considerado um comentário e ignorado pelo interpretador. A primeira linha do ficheiro é um caso especial, sob um sistema operativo do tipo Unix, isto indica á shell como executar o ficheiro. Os restantes comentários só se encontram ali para clarificação.

O nosso método dizer_ola tornou-se um pouco mais complexo:
# Dizer ola a todos
def dizer_ola
  if @nomes.nil?
    puts "..."
  elsif @nomes.respond_to?("each")
    # @nomes é uma lista de algum tipo, iterar!
    @nomes.each do |nome|
      puts "Ola #{nome}!"
    end
  else
    puts "Ola #{@nomes}!"
  end
end

Agora toma o parâmetro @nomes e toma decisões. Se for nil, só imprime três pontinhos. Não há razão para cumprimentar ninguém, certo?

Ciclos e Voltas-ou seja Iterações


Se o objeto @nomes responde a each, isto significa que é algo sobre o qual se pode iterar, assim, fazemos iterações sobre o mesmo e saudamos cada pessoa à sua vez. Finalmente, se @nomes é outra coisa qualquer, deixamos que se transforme numa string automaticamente e fazemos a saudação por omissão.
Vejamos o iterador com mais profundidade:
@nomes.each do |nome|
  puts "Ola #{nome}!"
end

each é um método que aceita um bloco de código e que depois o executa para cada elemento numa lista, e a parte entre do e end é exactamente um bloco desses. Um bloco é como uma função anónima ou lambda. A variável entre barras verticais é o parâmetro para este bloco.

O que sucede aqui é que para cada entrada na lista se associa nome a esse elemento da lista e depois a expressão puts "Ola #{nome}!" é executada com esse nome.

A generalidade das outras linguagens tratar de passar por uma lista usando o ciclo for, que em C se assemelha a algo como:
for (i=0; i

Isto funciona mas não é muito elegante. Necessitamos de uma variável descartável semelhante a i, temos que determinar previamente qual o tamanho da lista e temos que explicar como percorrer a lista. O modo de operar em Ruby é muito mais elegante, os trabalhos domésticos são escondidos dentro do método each, tudo o que necessitamos de lhe dizer é o que fazer com cada elemento. Internamente, o método each irá essencialmente chamar yield "Albert", depois yield "Brenda" e depois yield "Charles", e assim sucessivamente.

Blocos, Uma das funcionalidades mais poderosas da Ruby


O poder real dos blocos é quando tratam de algo mais complexo que listas. Para além de tratar dos detalhes simples de trabalhos domésticos dentro do método, também pode tratar da instalação, limpeza e erros?tudo de forma escondida das preocupações do utilizador.
# Dizer adeus a toda a gente
def dizer_adeus
  if @nomes.nil?
    puts "..."
  elsif @nomes.respond_to?("join")
    # Juntar os elementos da lista com vírgulas
    puts "Adeus #{@nomes.join(", ")}.  Voltem em breve!"
  else
    puts "Adeus #{@nomes}.  Volta em breve!"
  end
end

O método dizer_adeus não usa o método each, em vez disso verifica se @nomes responde ao método join e se sim, usa-o. Caso contrário limita-se a imprimir a variável como string. Este método não se preocupa com o verdadeiro tipo da variável, está só a limitar-se a tirar partido de algo conhecido por "Duck Typing", no sentido de que "se anda como um pato, e faz quá quá como um pato então?". A vantagem disto é não restringir desnecessariamente os tipos de variáveis suportados. Se alguém aparecer com um novo género de classe de lista, desde que essa lista tenha implementado método join com a mesma semântica que as outras listas, então tudo irá funcionar como planeado.

Executar o Script


Está pois apresentada a classe MegaAnfitrião, o resto do ficheiro só chama os métodos nessa classe. Existe um último truque a tomar nota, é a linha:
if __FILE__ == $0


__FILE__ é uma variável mágica que contém o nome do ficheiro actual. $0 é o nome do ficheiro usado para iniciar o programa. Esta verificação diz: "Se este é o ficheiro principal a ser usado então?", isto permite que um ficheiro seja usado como biblioteca e nesse contexto não executar código mas caso o ficheiro seja usado como executável então executa esse código.

Foi um prazer


Pronto, isto foi uma visita rápida ao mundo do Ruby. Existe muito para explorar, as diferentes estruturas de controlo que Ruby oferece, o uso de blocos e de yield, módulos como mixins e muito mais. Espero que esta pequena amostra da linguagem Ruby tenha deixado o desejo de aprender mais.

Se sim, por favor visite a nossa seção de Documentação, onde encontraram linkspara manuais e guias, todos disponíveis em formato digital.

Fonte: Ruby-lang.org

Mais sobre: ruby, dica
Share Tweet
DESTAQUESMais compartilhados
Comentários
AINDA NÃO SE INSCREVEU?

Vem ver os vídeos legais que
estamos produzindo no Youtube.