Para trabalhar com coleção de dados, filtrar informações, decidir quais instruções ou blocos de código serão executados, ordenar valores, converter um valor de um tipo para outro, entre outras operações, o Ruby fornece vários recursos que permitem executar essas operações. Analisaremos como funciona cada um em detalhes.

Para acompanhar os exemplos que serão mostrados nesse artigo é necessário ter instalado o Ruby em sua máquina., que dependerá do sistema operacional que está sendo usado. A fim de saber se a instalação foi efetuada com sucesso, abra o seu terminal ou prompt de comando e digite ruby --version ou o seu atalho equivalente ruby -v. A resposta deve ser algo parecido com o seguinte:

ruby 2.0 (2014-05-08) [x86_64-linux-gnu]

No pacote de instalação vem o IRB, que utilizaremos para executar alguns exemplos que serão mostrados neste artigo. Ele é uma ferramenta que faz a leitura de instruções ou códigos ruby e as interpreta instantaneamente, mostrando o resultado, além de ser muito usado para execução de testes rápidos. Para iniciar essa ferramenta basta digitar o comando “irb” no terminal.

Junto da instalação também encontramos o interpretador ruby, que serve para abrirmos os exemplos em que os códigos estarão em arquivos com a extensão “.rb”. Nestes casos será necessário invocá-lo no terminal ou console. Por exemplo, para que o código de um arquivo chamado teste.rb,, armazenado no diretório /home/daniel/exemplos-ruby/, seja executado basta digitar o comando a seguir no prompt ou terminal:

ruby /home/daniel/exemplos-ruby/teste.rb

Ou caso já tenha chegado pelo console até o diretório onde se encontra o arquivo (no exemplo apresentado - /home/daniel/exemplos-ruby/), bastaria digitar ruby teste.rb

A seguir passaremos para a parte prática do nosso artigo. Inicialmente conheceremos melhor métodos que podem nos ajudar na execução dos exemplos.

Praticando com Gets

Para começarmos a praticar, primeiro devemos estar com o IRB aberto.

Uma dica é o uso do método gets durante todo o artigo para deixar os exemplos mais dinâmicos e interessantes, pois ele pode ser usado no console para solicitar uma entrada de dados ao usuário. Assim, o que ele digitar será tratado como uma String, como vemos no exemplo da Listagem 1.

Listagem 1. Exemplo com IRB


  irb(main):001:0> nome = gets
  joão da silva souza
  irb(main):002:0> puts nome
  joão da silva souza
  => nil

Perceba que após digitar a instrução gets no terminal o irb ficará aguardando que seja digitado algo. Para o código da Listagem 1 o que for digitado será armazenado na variável nome e comprovamos isso ao imprimir a variável usando o método puts.

A partir da próxima seção entenderemos mais algumas estruturas de dados para colocar os nossos exemplos em prática.

Estruturas de Controle de fluxo

Algumas aplicações necessitam decidir o que vai ser executado baseado em alguma condição. Para isso a linguagem Ruby disponibiliza recursos que são chamados estruturas de decisão, que tem o objetivo de controlar justamente o fluxo de execução da aplicação.

Precisamos antes conhecer alguns operadores que farão parte das condições a serem analisadas nos códigos. Para isso acompanhe as próximas seções.

Operadores aritméticos

Os operadores aritméticos na linguagem ruby são métodos dos objetos que representam números. Pode-se comprovar isso ao chamar o método methods, que retorna todos os métodos disponíveis para um objeto. Se essa chamada for feita, por exemplo, em uma instância de um objeto Fixnum, a resposta conterá o seguinte:

:+,  :-,  :*,  :/

Isso indica que esse objeto reponde aos métodos + (adição) – (subtração) * (multiplicação) e / (divisão), que podem, inclusive, serem sobrescritos mudando o seu comportamento. A chamada a esses métodos é feita de forma transparente, o que faz com que o desenvolvedor imagine o método como um operador.

Operadores relacionais

Os operadores relacionais são facilmente entendidos visto que são bastante utilizados na matemática, conforme vemos na Tabela 1.

Símbolo Descrição Exemplo Resultado
> Maior que 6 > 8 Falso
< Menor que 7< 10 Verdadeiro
>= Maior ou igual a 8 >= 8 Verdadeiro
<= Menor ou igual a 7 <= 2 Falso
!= Diferente de != 8 Verdadeiro
== Igual a 10 = 10 Verdadeiro

Tabela 1. Operadores Relacionais

Não se deve fazer confusão entre os operadores “==” e “=”, pois o primeiro serve para comparar a igualdade enquanto o segundo serve como atribuição.

Operadores lógicos

Os operadores lógicos têm o objetivo de fazer uma junção entre condições resultando em um novo valor booleano, conforme vemos na Tabela 2.

Operador Descrição Exemplo Resultado
and / && E 6 > 8 and 7 > 8 Falso
or / || Ou 10< 10 or 15 > 1 Verdadeiro
not / ! Não ! true Falso

Tabela 2. Operadores lógicos

A diferença entre os operadores “e” e “ou” é que o primeiro retorna verdadeiro apenas se as duas expressões retornarem verdadeiras e a segunda retorna verdadeiro mesmo que uma das expressões seja avaliada como falsa. Já o operador not inverte o valor lógico de true para false e vice-versa. Na Listagem 2 temos alguns exemplos executados no IRB.

Listagem 2. Exemplos com operadores


  irb(main):001:0> 10 < 8 and 7 > 5
  => false
  irb(main):002:0> 8 == 9 or 6 > 3
  => true
  irb(main):003:0> 10 > 9 && 1 > 0
  => true
  irb(main):004:0> 7 == 7 || 6 > 8
  => true
  irb(main):005:0> not(10 == 10)
  => false
  irb(main):006:0> !false
  => true

A partir das próximas seções conheceremos algumas estruturas de decisão e que usarão os operadores apresentados.

Estruturas de decisão

If

Instruções if's são usadas para decidir se determinada instrução será executada. Imagine que o usuário deva digitar a sua idade e esse é avaliado. Na Listagem 3 o código usa uma instrução if para fazer essa validação.

Listagem 3. Exemplo com if


  puts "Informe a sua idade"
  idade = gets.to_i
  if idade < 0
   puts "essa não é uma idade válida"
  end

A primeira instrução no código solicita ao usuário que digite a idade do mesmo e em seguida o valor retornado pelo método gets é convertido em um inteiro através da chamada ao método to_i e é armazenado na variável idade. Na linha 3 é vista a instrução if que “pergunta” se a idade digitada é menor que zero, ou seja, se ela é negativa: caso isso seja verdade a mensagem “essa não é uma idade válida” será impressa no console.

Else

Essa instrução é executada caso a condição if não seja verdadeira. É possível incrementar o exemplo da Listagem 3 com a instrução else, como mostra a Listagem 4.

Listagem 4. Exemplo com else


  puts "Informe a sua idade"
  idade = gets.to_i
  if idade < 0
   puts "essa não é uma idade válida"
  else
   puts "essa é uma idade válida"
  end

Quando o usuário digitar uma idade maior que zero ele receberá a mensagem “essa é uma idade válida”.

Elsif

Caso seja necessário validar mais de uma condição, a instrução elsif pode ser usada. Por exemplo, imagine um caso em que se deve verificar se a idade de um usuário é compatível com o conteúdo que ele deseja acessar. Veja como fica o exemplo na Listagem 5.

Listagem 5. Exemplo com elsif


  puts "Informe a sua idade"
  idade = gets.to_i
  if idade >= 0 and idade < 18
    puts "ops! você não tem acesso a esse conteúdo"
  elsif idade >= 18
    puts "Olá! seja bem vindo, visitante!"
  else
    puts "Essa não é uma idade válida"
  end

A instrução if verifica se a idade digitada pelo usuário é maior ou igual a 0 (>=) e (and) < 18. Caso essa condição não satisfaça, o interpretador verificará a condição passada para a instrução elsif, que afere se a variável idade é maior ou igual a 18 (>=). Caso essa instrução retorne true (verdadeiro), a mensagem “Olá! seja bem vindo, visitante!” será impressa. Em seguida, a instrução else será executada se nenhuma das duas instruções anteriores forem verdadeiras - por exemplo, no caso do usuário digitar um valor negativo.

Unless

A instrução unless (a menos que) tem o funcionamento oposto ao if, ou seja, o bloco de código associado só será executado caso a condição seja falsa. Veja o código da Listagem 6 em que o resultado impresso é “x é menor ou igual a 15”.

Listagem 6. Exemplo com Unless

x = 10
  unless x > 15 # → a menos que x seja maior que 15
    puts "x é menor ou igual a 15"
  else
   puts "x é maior que 15"
  end

Case

No caso de ser necessário avaliar uma expressão e houverem muitas condições, a instrução case é preferível ao invés da instruçãoif, como na Listagem 7.

Listagem 7. Exemplo com case

puts "Informe sua idade"
  idade = gets.to_i
  case idade
  when 0..12
   puts "você é uma criança"    
  when 13..17
   puts "você é um adolescente"
  else
   puts "você é um adulto"
  end

When

A instrução when (quando) testa se o valor informado está entre os ranges (intervalos) delimitados por dois números inteiros. É possível fazer o mesmo usando if's, mas é notável a perda de legibilidade, como mostra o exemplo da Listagem 8.

Listagem 8. Exemplo com When

puts "Informe sua idade"
  idade = gets.to_i
   
  if idade < 12
    puts "você é uma criança"   
  elsif idade >= 13 and idade <= 17
    puts "você é um adolescente"
  else
    puts "você é um adulto"
  end

Exemplo prático – Estruturas de decisão

Para completar o aprendizado visto até agora, vamos criar uma calculadora que utiliza as instruções da linguagem, como mostra a Listagem 9.

Listagem 9. Calculadora

puts "informe o primeiro operando"
  operando1 = gets.to_i
   
  puts "informe o segundo operando"
  operando2 = gets.to_i
   
  puts "informe 1 para soma 2 para subtração 3 para multiplicação e 4 para divisão"
  operacao = gets.to_i
   
  case operacao
  when 1
    puts "O resultado é #{operando1 + operando2}"
  when 2
    puts "O resultado é #{operando1 - operando2}"
  when 3
    puts "O resultado é é #{operando1 * operando2}"
  when 4
    puts "O resultado é #{operando1 / operando2}"
  else
    puts "Operação inválida"
  end

Neste exemplo usamos o método gets para capturar os valores que o usuário digitar para os dois operandos e também para a operação desejada. Em seguida foi usada a instrução case para determinar qual das quatro operações deve ser realizada com os operandos informados.

Concluído o aprendizado sobre as estruturas condicionais, aprenderemos a seguir sobre as estruturas de repetição, que podem ser usadas com as que aprendemos até agora.

Estruturas de repetição

As estruturas de repetição são também muito usadas para executar uma determinada operação várias vezes como, por exemplo, percorrer ou iterar uma lista de produtos para mostrar o nome de cada um ou para efetuar o cálculo do valor total deles. A seguir veremos as estruturas de repetição mais usadas na linguagem ruby.

While

Podemos usar o a instrução while para executar determinada tarefa um número específico de vezes. A sintaxe para o uso dessa expressão é a seguinte:

while [codicao] do
    # operação a ser repetida aqui
  end

Veja na Listagem 10um exemplo para essa instrução com uma contagem simples de 0 a 10 usando o IRB.

Listagem 10. Exemplo com While

irb(main):001:0> contador = 0
  => 0
  irb(main):002:0> while contador <= 10 do
  irb(main):003:1* print "#{contador}, "
  irb(main):004:1> contador += 1
  irb(main):005:1> end
  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, => nil

Note que para este caso foi usada uma variável (contador) que armazenou, a cada iteração, o valor corrente, que a cada iteração teve o seu valor incrementado com mais 1: isso é importante para que a condição seja em algum momento satisfeita, evitando um loop infinito.

Until

Boa parte das linguagens famosas hoje em dia não colocam a disposição do desenvolvedor uma estrutura semelhante a essa. O bloco de código associado a ela só é executado a menos que determinada condição seja satisfeita, ou seja, para que o código seja executado é necessário que a condição retorne false.Quando ela retornar true o bloco para de ser executado, como vemos na sintaxe a seguir:

until [condicao] do
    # operação a ser repetida aqui
  end

O exemplo da Listagem 11, executado no IRB, mostra o seu funcionamento.

Listagem 11. Exemplo com until

irb(main):001:0> contador = 10
  irb(main):002:0> until contador == 0 do
  irb(main):003:1* print "#{contador}, "
  irb(main):004:1> contador -= 1
  irb(main):005:1> end
  10, 9, 8, 7, 6, 5, 4, 3, 2, 1, => nil

O exemplo confirma que quando a condição retorna verdadeiro (neste caso quando o contador se tornou igual a zero) o bloco de código para de ser executado.

For

A estrutura for é bem semelhante ao while, com a diferença de que tem a declaração da variável, que auxilia as iterações em sua própria estrutura, como mostra a sintaxe a seguir:

for [elemento] in [elementos_a_serem_percorridos] do
  end

Em ruby essa estrutura é mais frequentemente usada para percorrer lista de objetos que tenham implementado o método each, que é um método que aceita um bloco de código e que depois o executa para cada elemento numa lista. Uma tentativa de usá-lo em um tipo numérico como Fixnum resultaria em um erro, como vemos na Listagem 12.

Listagem 12. Exemplo com for

irb(main):001:0> for contador in 10 do
  irb(main):002:1* print #{contador}, "
  irb(main):003:1> end
  NoMethodError: undefined method `each' for 10:Fixnum
              from (irb):1
              from /usr/bin/irb:11:in `<main>'

O método each está disponível por exemplo paraarray's e range's. O problema relatado pode ser corrigido usando um range (intervalo), como mostra a Listagem 13.

Listagem 13. Exemplo com each

irb(main):001:0> for e in 0..10 do
  irb(main):002:1* print "#{e}, "
  irb(main):003:1> end
  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, => 0..10

Repare que não foi necessário incrementar a variável “e”, pois a própria estrutura de repetição se encarrega de armazenar o próximo elemento nesta variável.

Com o for também é possível percorrer elementos em um array, como mostra a Listagem 14.

Listagem 14. Exemplo com array

irb(main):001:0> linguagens = ["ruby", "java", "python", "php", "lua"]
  irb(main):002:0> for linguagem in linguagens do
  irb(main):003:1* print "#{linguagem}, "
  irb(main):004:1> end
  ruby, java, python, php, lua

Existe também a possibilidade de percorrer estruturas mais complexas como os hash's. A interação com um desses é levemente diferente do array, já que cada elemento inserido em um hash é um conjunto de chaves associado a um valor. Em cada iteração do for o conjunto chave e valor é colocado em um arraypara acessá-los por meio dos seus índices, como mostra a Listagem 15.

Listagem 15. Exemplo com hash

irb(main):001:0> produtos = {:mouse=>30.0, :monitor=>500.0, :fone=>90.0}
  irb(main):002:0> for produto in produtos do
  irb(main):003:1* puts "#{produto[0]} - #{produto[1]}"
  irb(main):004:1> end
  mouse - 30.0
  monitor - 500.0
  fone - 90.0

O exemplo parece muito verboso e não elegante, por isso o ruby disponibiliza ainda outra maneira de percorrer os elementos de um hash com o método each, assim não é necessário acessar o conjunto chave e valor por meio de índices, como mostra a Listagem 16.

Listagem 16. Exemplo de hash com each

irb(main):001:0> produtos = {:mouse=>30.0, :monitor=>500.0, :fone=>90.0}
  irb(main):002:0> produtos.each do |produto, preco|
  irb(main):003:1* puts "#{produto} - #{preco}"
  irb(main):004:1> end
  mouse - 30.0
  monitor - 500.0
  fone – 90.0

E ainda, se for necessário iterar apenas sobre as chaves ou sobre os valores, temos os métodos each_key e each_value, como mostra os exemplos da Listagem 17.

Listagem 17. Exemplos com each_key e each_value

irb(main):001:0> produtos = {:mouse=>30.0, :monitor=>500.0, :fone=>90.0}
  => {:mouse=>30.0, :monitor=>500.0, :fone=>90.0}
  irb(main):002:0> produtos.each_key do |produto|
  irb(main):003:1* print "#{produto}, "
  irb(main):004:1> end
  mouse, monitor, fone
   
  irb(main):001:0> produtos = {:mouse=>30.0, :monitor=>500.0, :fone=>90.0}
  => {:mouse=>30.0, :monitor=>500.0, :fone=>90.0}
  irb(main):002:0> produtos.each_value do |produto|
  irb(main):003:1* print "#{produto}, "
  irb(main):004:1> end
  30.0, 500.0, 90.0

Times

A linguagem ruby ainda disponibiliza o iterador chamado times (vezes). Se é necessário executar uma tarefa um número determinado de vezes isso pode ser feito da seguinte maneira:

irb(main):001:0> 5.times{print "Devmedia "}
  Devmedia Devmedia Devmedia Devmedia Devmedia => 5

Se o código a ser executado precisa estar disposto em mais de uma linha, as chaves devem ser substituídas pelas palavras reservadas do e end, como mostrado na Listagem 18.

Listagem 18. Exemplo com times

irb(main):001:0> 5.times do
  irb(main):002:1* print "Devmedia "
  irb(main):003:1> end
  Devmedia Devmedia Devmedia Devmedia Devmedia => 5

Também é possível usar o iterador times com uma variável contadora ou de iteração. O código da Listagem 19mostra como.

Listagem 19. Exemplo com variável

 
  irb(main):001:0> 10.times do |contador|
  irb(main):002:1* print "#{contador} "
  irb(main):003:1> end
  0 1 2 3 4 5 6 7 8 9 => 10

Exemplo prático – Estruturas de repetição

Este tópico mostra a criação de um exemplo simples utilizando recursos que já foram apresentados. Mas para este exemplo é necessário um pequeno conhecimento a respeito do método rand, que escolhe aleatoriamente um número baseado em um limite ou intervalo. Veja na Listagem 20um pequena demonstração de como ele funciona.

Listagem 20. Exemplo com rand

irb(main):001:0> rand(3)
  => 0
  irb(main):002:0> rand(3)
  => 2
  irb(main):003:0> rand(3)
  => 1
  irb(main):004:0> rand(0..3)
  => 1
  irb(main):005:0> rand(0..3)
  => 2
  irb(main):006:0> rand(0..3)
  => 3

Neste exemplo esse método será usado para escolher um número aleatório, que deverá ser adivinhado pelo usuário. Também será usada a estrutura de controle while, bem como o método gets, como mostra a Listagem 21.

Listagem 21. Exemplo de controle While

numero = rand(0..15)
  puts "Tente adivinhar o número escolhido pela máquina de 0 a 15"
  numero_chute = gets.to_i
  while numero != numero_chute do
    puts "Ooops! Tente novamente!"
    numero_chute = gets.to_i
  end
  puts "Parabens você acertou! O número é: #{numero}"

A aplicação inicia usando o método rand para escolher um número aleatório entre 0 e 15. Depois disso solicita ao usuário que informe um número qualquer que será o seu palpite. O laço while é usado para continuar solicitando ao usuário outros palpites até que ele consegue a acertar o número inicialmente escolhido e assim o programa encerra.

Ao longo desse artigo você pode perceber que programar com ruby não envolve muita dificuldade, pois ela é uma linguagem bem simplificada a nível de quantidade de código. As estruturas aprendidas aqui são essenciais para o desenvolvimento de qualquer aplicativo, por menor que seja.

Referências

Ruby lang
https://www.ruby-lang.org/pt

Ruby doc
http://ruby-doc.org/core-1.9.3/Random.html

DotNet Perls
http://www.dotnetperls.com/iterator

Techotopia
http://www.techotopia.com/index.php/Ruby_While_and_Until_Loops