Вы находитесь на странице: 1из 19

Ruby 101 O bsico de Ruby para poder utilizar tanto o Rails quanto o Cucumber

A idia deste post no ser um compendio universal de conhecimento sobre Ruby, bem longe disto inclusive, a idia ter apenas uma pequena introduo, apresentar a vocs alguns conceitos bsicos, para que aqueles que j programam em alguma outra linguagem consigam brincar um pouco com Ruby, e principalmente para que consigam entender o cdigo dos posts sobre Ruby, Rails e Cucumber do blog, ento espero que aproveitem, mesmo no sendo a melhor introduo a linguagem Ruby, espero que ajude.

O que o Ruby
Uma linguagem dinmica, open source com foco na simplicidade e na produtividade. Tem uma sintaxe elegante de leitura natural e fcil escrita.

Interactive Ruby
No incio dessa jornada pelo Ruby, vamos utilizar o irb, sigla em ingls para Interactive Ruby (Ruby Interativo). Esse utilitrio muito usado para testar cdigos antes de pass-los para o arquivo de destino, permitindo um teste mais rpido e, portanto, uma correo mais rpida dos possveis problemas. Abra um terminal e digite irb. Voc ver um prompt como este:
1 irb(main):001:0>

Agora, voc est pronto para comear a utilizar o Ruby como uma calculadora! Lembre-se de que todos os comandos mostrados nas prximas pginas podem ser testados neste aplicativo. Ento, vamos aprender um pouco sobre o irb antes de continuar. Se voc digitar 1+1 e pressionar Enter, na prxima linha vai aparecer:
1 => 2

e o prompt muda para:


1 irb(main):002:0>

Ou seja, os nmeros entre os dois pontos so correspondentes linha do comando, como se fosse a linha do arquivo na edio de um arquivo .rb (extenso padro para programas Ruby). Tambm podemos concluir que toda e qualquer expresso em Ruby tem um valor de retorno, que mostrado no irb, no caso o => 2, que o resultado da soma realizada. O ltimo nmero o nvel do bloco atual. No Ruby, tudo um objeto, incluindo nmeros. O que fizemos neste exemplo foi enviar a mensagem + para o objeto 1, com o argumento 1, e essa mensagem retorna um resultado que a soma desses nmeros, no caso 2. Esse conceito de enviar mensagens para objetos vai ser muito importante mais adiante.

Introduo ao Ruby
Todos os cdigos apresentados, voc podera escrever linha a linha no IRB para ver o que acontece a cada linha, para facilitar a escrita do tutorial e a posterior atualizao do mesmo, vou colocar todos os cdigos em arquivos .rb, para executar estes arquivos, salve o arquivo e execute: ruby e voc vera o resultado da execuo no console. Vamos comear com o bsico do bsico, como definir um mtodo no ruby, na verdade no estamos definindo um mtodo, estamos registrando um endereo para que o carteiro interno do ruby possa entregar mensagens a um objeto, estamos definindo os nomes das mensagens que este objeto pode receber, mas para fazer isto, utiliza-se a palagra def como no exemplo a seguir:

intro/01soma.rb
1 def soma a, b 2 a + b 3 end 4 5 puts soma 1, 2

No Ruby no necessrio utilizar return ou qualquer palavra-chave para definir o retorno de um mtodo. O retorno do mtodo o valor da ltima expresso executada, em nosso caso, a+b. Os parnteses so opcionais em quase todas as situaes. Por exemplo, poderamos reescrever o exemplo anterior da seguinte forma: intro/02soma.rb
1 def soma(a, b) 2 a + b 3 end 4 5 puts soma(1, 2)

Como podemos verificar no exemplo, alm dos parnteses, o ; no final das sentenas tambm opcional, tornando a sintaxe bastante flexvel. No Ruby, tudo um objeto, e todo objeto pertence a uma classe. Todas as classes descendem de Object, e possvel verificar em tempo de execuo qual o tipo do objeto, como pode ser visto a seguir: intro/03objects.rb
1 2 3 4 5 6 7 puts puts puts puts puts puts puts 1.class self.class [].class ({}.class) "a".class 1.1.class 99999999999999999999.class

A palavra-chave self utilizada para identificar o objeto atual, o nmero 1 do tipo Fixnum, o nmero 1.1 do tipo Float e um nmero muito grande do tipo Bignum. No necessrio se preocupar se um nmero Fixnum ou Bignum, pois o Ruby vai cuidar das converses automaticamente. Ok, mas em que saber isso pode ser til? Fcil: a classe Fixnum, por consequncia, a instncia dessa classe 1, tem diversos mtodos teis para trabalhar com nmeros, e graas ao irb, no precisamos decorar todos os mtodos. intro/04methods.rb
1 puts 1.methods.sort

A classe Object tem o mtodo methods, que retorna um Array contendo todos os mtodos disponveis para aquele objeto, neste caso, o nmero 1. Como podemos verificar pelo resultado do mtodo methods, as operaes matemticas tambm so mtodos da classe Fixnum, como o +, *, -, / e assim por diante.

Classes abertas em tempo de execuo


O Ruby tem um recurso bastante interessante, que o torna uma linguagem muito flexvel. Esse recurso se chama open classes, ou seja, todas as classes do Ruby esto sempre abertas, o que possibilita que elas sejam alteradas a qualquer momento. Isso bastante til, mas tambm bastante perigoso. Para demonstrar o perigo que isso representa em mos incautas, faremos uma pequena brincadeira: intro/05openclass.rb

1 class Fixnum 2 def +(other) 3 self - other 4 end 5 end 6 puts 1 + 5

O que acabamos de fazer foi alterar o mtodo + da classe Fixnum, o que pode causar uma grande confuso, como visto no exemplo, fazendo com que o mtodo + realize, na verdade, uma operao de subtrao. No entanto, esse recurso, quando utilizado corretamente, pode ajudar bastante no desenvolvimento de aplicaes, como veremos mais adiante.

Variveis
Variveis no Ruby podem conter dados de qualquer tipo. Voc pode usar variveis em seus programas Ruby sem qualquer declarao. O nome de uma varivel por si s denota seu escopo (local, global, instncia, etc). O nome de uma varivel local (declarada dentro de um objeto) consiste de uma letra minscula (ou um underscore) seguido por caracteres de nome (azul, z, bater_ecorrer). O nome de uma varivel de instncia (declarada dentro de um objeto sempre pertence a qualquer que seja o objeto que self se refira) comea com uma arroba (@) seguida por um nome (@assinatura, @_, @contador). O nome de uma varivel de classe (declarada dentro de uma classe) comea com duas arrobas (@@) seguidas de um nome (@assinatura, @_, @@contador). Uma varivel de classe compartilhada por todos os objetos de uma classe. Somente uma cpia de uma varivel de classe particular existe para uma dada classe. Variveis de classe usadas no nvel mais alto so definidas em Object e se comportam como variveis globais. Essas so raramente utilizadas em programas Ruby. Variveis globais comeam com um smbolo de dlar ($) seguido por caracteres de nome. O nome de uma varivel global tambm pode ser formado usando $- seguido por qualquer caractere nico ($contador, $CONTADOR, $-x). O Ruby define uma srie de variveis globais que incluem outros caracteres de pontuao, como $_ e $-K.

Variveis e escopo
No Ruby, no necessrio declarar uma varivel: ela ser definida no momento em que tiver um valor atribudo. Para que isso seja possvel, o Ruby utiliza tipagem dinmica, ou seja, ele define o tipo de uma varivel por seu valor, mas isso no quer dizer que seja uma linguagem de tipagem fraca, pois no possvel somar um nmero com uma string, como pode ser visto no seguinte cdigo-fonte: intro/06strongtype.rb
1 puts 1 + "2"

Se voc executar este cdigo, recebera um erro, informando que no possvel misturar variveis de tipos diferentes. O Ruby no tem palavras-chave para definir o escopo de variveis: isso feito por meio de smbolos, como na lista a seguir: Smbolo nome @nome @@nome $nome Varivel local. Varivel de instncia. Varivel de classe. Varivel global. Descrio

Tipos bsicos do Ruby


Blocos de cdigo
Blocos de cdigo consistem em um dos recursos mais versteis e flexveis do Ruby. So utilizados para iterar em colees, personalizar o comportamento de algum mtodo e definir Domain Specific Languages. Para quase tudo so usados blocos de cdigo, at para criar formulrios para pginas da web no Rails e definir boa parte das configuraes do framework. Existem duas sintaxes diferentes para definir um bloco de cdigo. Pode-se fazer isso utilizando os smbolos { e } ou utilizando as palavras-chave do e end. Blocos de cdigo podem receber parmetros. Para definir a lista de parmetros, logo depois de aberto o bloco de cdigo utilizado o smbolo | para demarcar o incio e o fim da lista de parmetros. O Ruby tem suporte a closures reais. Isso quer dizer que, se em um bloco de cdigo forem utilizadas variveis visveis no contexto da criao do bloco, qualquer alterao nessas variveis vai ser refletida no contexto original, ou seja, os blocos de cdigo tm um link com o contexto de origem, o que os torna mais teis ainda e os diferencia muito de ponteiros para mtodos do C/C++, por exemplo.

intro/07codeblock.rb
1 arr = [1, 2, 3, 4] 2 arr.each { |val| 3 print "#{val}\n" 4 }

Esse exemplo utiliza um bloco de cdigo simples, delimitado por chaves para iterar nos valores de um array. Veja que o valor do array no foi alterado pelo retorno da expresso. intro/08codeblock.rb
1 arr = [1, 2, 3, 4] 2 arr.each_with_index do |val, idx| 3 print "Posicao #{idx} valor #{val}\n" 4 end

Esse segundo exemplo faz praticamente a mesma coisa, mas utiliza outro mtodo de iterao, que passa alm do valor. O ndice fornece o valor no array e, dessa vez, so utilizados os delimitadores do e end. intro/09closure.rb
1 2 3 4 5 6 arr = [1, 2, 3, 4] valor = 1 arr.each do |val| valor += val end puts valor

J nesse exemplo utilizada uma closure, em vez de um bloco de cdigo simples. A diferena bsica que a closure mantm o contexto de onde ela chamada, neste caso, alterando a varivel local valor. Podemos ver no prximo exemplo que, se for utilizado um mtodo para realizar essa iterao, a varivel valor no vai existir, o que vai causar um erro que prova que o bloco aponta para seu contexto de origem. intro/15scope.rb
1 2 3 4 5 6 valor = 1 def iterar arr = [1, 2, 3, 4] arr.each do |val| valor += val

7 end 8 end 9 10 iterar

Esse exemplo tambm demonstra uma das convenes para a nomenclatura de variveis apresentada no exemplo anterior, ou seja, variveis que no tm seus nomes iniciados por @, @@ ou $ so variveis locais no contexto onde foram definidas. possvel tambm passar blocos de cdigo como parmetros para mtodos. Isso muito usado na API padro do Ruby, e pode ser visto inclusive no exemplo anterior, quando passamos um bloco de cdigo como parmetro para o mtodo each da classe Array. No prximo exemplo, veremos como criar um mtodo que recebe um bloco de cdigo como parmetro, ou seja, como utilizar um bloco de cdigo passado para um mtodo. No ser mostrado como armazenar um bloco de cdigo em uma varivel, porque nesse caso, o bloco de cdigo se transforma em uma instncia da classe Proc e esse um assunto para o prximo captulo.

intro/16blockparam.rb
1 2 3 4 5 6 7 8 9 10 def recebe_proc_e_passa_parametro if block_given? yield else puts "voc precisa passar um bloco para este mtodo\n" end end recebe_proc_e_passa_parametro recebe_proc_e_passa_parametro { print "dentro do bloco\n" }

Podemos tambm passar parmetros para blocos recebidos nos mtodos: intro/17blockparam.rb
1 2 3 4 5 6 7 8 9 10 11 12 #encoding : UTF-8 def recebe_proc_e_passa_parametro if block_given? yield(23) else puts "voc precisa passar um bloco para este mtodo\n" end end recebe_proc_e_passa_parametro do |par| puts "Recebi #{par} dentro deste bloco\n" end

Procs
Procs so muito parecidos com blocos de cdigo ou closures simples, que foram vistos na seo anterior. A diferena bsica que podemos armazenar um proc em uma varivel, e isso torna um pouco mais caro para o Ruby a implementao de procs do que simples blocos de cdigo. Por isso, tiveram a brilhante ideia de, internamente no Ruby, utilizar dois elementos diferentes para representar essas duas entidades que, para o programador usurio da linguagem, so praticamente iguais. Alm disso, o Ruby converte blocos de cdigo em procs de forma transparente, fazendo com que na maioria das situaes no seja necessrio se preocupar com esse tipo de detalhe. Para deixar isso um pouco mais claro

veremos alguns exemplos a seguir: Converter um bloco recebido em um proc. intro/18proc.rb


1 def recebe_proc(&block) 2 if block 3 block.call 4 end 5 end 6 7 recebe_proc 8 9 recebe_proc { print "este bloco

vai se tornar uma proc pois vai ser atribudo a uma varivel

no mtodo" }

Criar uma varivel do tipo Proc de duas formas diferentes. intro/19proc.rb


1 2
p = Proc.new { print "este bloco vai se tornar uma proc pois est sendo atribudo a uma varivel\n" } p.call

intro/20lambda.rb
1 p1 = lambda do 2 print "este bloco vai se tornar uma proc pois est sendo atribudo a uma varivel\n" 3 end 4 p1.call

Nestes exemplos, foi possvel verificar as duas formas de criar um objeto do tipo Proc: utilizando o construtor da classe Proc (leia mais sobre construtores na seo sobre classes) ou utilizando a palavra-chave lambda, de modo semelhante ao Python. Como Proc uma classe, objetos desse tipo tm diversos mtodos. Vejamos alguns destes de forma mais detalhada: intro/21procclass.rb
1 p = Proc.new { print "a" } 2 puts p.methods.sort

Diversos mtodos padro da classe Object do Ruby so listados, pois como todas as classes, a classe Proc tambm descendente de Object, ou seja, procs so objetos comuns no Ruby. Retomando o tpico anterior, existem alguns mtodos que so mais interessantes para ns neste momento: Descrio Utilizado para executar o proc, os parmetros que forem definidos no bloco so passados como call parmetros para o mtodo call. [] Alias para o mtodo call, ou seja, podemos executar um proc com a sintaxe: p[parmetros]. arity Informa o nmero de parmetros definidos nesse proc. Retorna a Binding correspondente ao local onde foi definido o bloco de cdigo que deu origem a esse binding proc. Mtodo

Nmeros
Como em todas as linguagens de programao, o Ruby tem suporte a processamento numrico, mas diferente de muitas das linguagens, mesmo algumas das supostamente orientadas a objetos, no Ruby todos os nmeros so objetos, portanto, todos so instncias de alguma classe. O Ruby tem trs classes que representam nmeros. So elas: Classe Descrio Fixnum Representa inteiros de -1073741824 a 1073741823.

Bignum Representa inteiros fora do intervalo da classe Fixnum. Float Representa nmeros de ponto flutuante. Para definir um nmero de ponto flutuante basta utilizar um ponto .. Se voc quiser muito separar milhares, pode utilizar o _, mas no recomendo a utilizao, pois o visual da sintaxe fica poludo. A seguir esto alguns exemplos de nmeros no Ruby. intro/22numberandclass.rb
1 2 3 4 5 6 7 8 9 10 11 12 def number_and_class(n) puts "#{n} -> #{n.class}" end i =1 i1 = 1.1 i2 =111_222_333 i3 =999999999999999999 number_and_class i number_and_class i1 number_and_class i2 number_and_class i3

Como j foi dito, o Ruby utiliza duas classes diferentes para tratar inteiros. No necessrio se preocupar com isso, pois a converso entre esses tipos feita automaticamente pelo interpretador, ou seja, se um nmero ficar grande demais para caber em um Fixnum, ele ser convertido para Bignum. Caso ele volte a estar no intervalo do Fixnum, essa classe ser utilizada novamente.

Valores booleanos
Valores booleanos, como na maior parte das linguagens de programao, so representados por true e false, ou verdadeiro e falso, respectivamente. Entretanto, no Ruby existe uma particularidade: a palavra-chave nil, que representa nenhum objeto, considerada como falsa em qualquer comparao. Portanto, existem dois valores para falso, e quaisquer outros valores sero considerados como verdadeiros. Resumindo, as comparaes booleanas servem tambm para verificar se uma varivel tem um valor. Veja alguns exemplos que exemplificam melhor o que voc acabou de ler: intro/23boolean.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #encoding: UTF-8 def testa_valor(val) if val print "#{val} considerado verdadeiro pelo Ruby\n" else print "#{val} considerado falso pelo Ruby\n" end end testa_valor true testa_valor false testa_valor 1 testa_valor "asda" testa_valor nil

Strings
Strings so o tipo de dados utilizados para representar texto dentro do cdigo. O Ruby tem dois tipos de string, que so diferentes apenas durante sua declarao. Um dos tipos tem expanso de variveis e suporta caracteres

especiais, como os do C, por exemplo, \n para representar uma quebra de linha. Alm desses dois tipos de strings, o Ruby tem diversas formas de declarar strings no cdigo: Smbolo aspas apstrofes < %Q{ } %q{ } Descrio String simples com expanso de variveis. String simples sem expanso de variveis. String multilinha com expanso de variveis. String multilinha com expanso de variveis. String multilinha sem expanso de variveis.

Veja alguns exemplos de declarao de strings no Ruby: intro/24strings.rb


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 a = "texto" b = 'texto' c = "texto\nsegunda linha" d = 'texto\nmesma linha' e = "a = #{a} - assim que se utiliza expanso de variveis" f = <<__ATE_O_FINAL esta uma String bem grande e s tesmina quando encontrar o marcador __ATE_O_FINAL no incio de uma linha __ATE_O_FINAL g = %Q{Esta tambm uma String com mais de uma linha e tambm suporta #{a} expanso de variveis } h = %q{J esta que tambm multi linha no suporta #{a} expanso de variveis} puts a puts b puts c puts d puts e puts f puts g puts h

Como podemos ver no exemplo anterior, as strings do Ruby suportam um recurso bastante interessante chamado expanso de variveis, que, na verdade, suporta execuo de cdigo Ruby dentro de uma String. Para utilizar isso, basta colocar o cdigo a ser executado dentro dos smbolos #{ e }. O cdigo ser executado, e o resultado da expresso ser includo dentro do texto original. Isso bastante til ao se trabalhar com output de texto, seja para exibio aos usurios, seja para criao de arquivos.

Constantes
O Ruby no tem algo que seja realmente constante, mas a linguagem tem um padro que diz que variveis declaradas com a primeira letra maiscula so constantes. A linguagem no o impede de alterar o valor dessa constante se voc realmente quiser: o Ruby vai apenas imprimir um aviso dizendo que voc realmente no deveria estar fazendo isso, como mostra o exemplo a seguir: intro/25constants.rb
1 2 3 4 CONSTANTE CONSTANTE Constante Constante = = = = "asda" 1 2 5

Intervalos numricos
Alm de nmeros simples, possvel declarar intervalos numricos no Ruby. O Ruby tem dois tipos de intervalos numricos: o inclusivo, que inclui o ltimo nmero, e o exclusivo, que no inclui esse nmero. Intervalos inclusivos e exclusivos so declarados utilizando os smbolos .. e , respectivamente, como pode ser visto no exemplo a seguir: intro/26numericintervals.rb
1 2 3 4 5 6 7 8 9 a = 1..10 b = 1...10 a.each do |v| print "#{v} " end print "\n" b.each do |v| print "#{v} " end

Arrays
Arrays so colees de valores. No Ruby, arrays no so tipados, ou seja, um array pode conter objetos de diversos tipos. Existem duas formas de se declarar um array genrico e uma forma extra de se declarar um array contendo apenas strings, como podemos ver no exemplo a seguir: intro/27arrays.rb
1 2 3 4 5 arr = [] arr = ['a', 1] arr = Array.new arr = %w{ a b c } puts arr.methods.sort

Junto com os hashes, arrays so as estruturas de dados mais utilizadas na linguagem Ruby, principalmente pela flexibilidade e facilidade de iterao pelo contedo de um array. Como vimos nos outros exemplos, bastante fcil percorrer um array utilizando o mtodo each, ou each_with_index. Alm desses, os arrays tm diversos outros mtodos que sero muito teis durante o desenvolvimento das aplicaes Rails. Alguns desses esto na lista a seguir: Mtodo select []= [] last empty? Descrio Recebe um bloco e retorna um novo array contendo todos os elementos para os quais o bloco retornou true. Define o valor de uma posio no array. Retorna o valor da posio passada como parmetro. Retorna o ltimo item do array. Retorna verdadeiro se o array estiver vazio.

equal? Compara com outro array. each_inde Recebe um bloco e passa apenas os ndices do array para o bloco. x Retorna um novo array contendo os itens deste ordenados. Opcionalmente recebe um bloco com dois sort parmetros, o qual deve retornar qual dos itens menor, fazendo assim uma comparao personalizada. sort! Similar ao sort, mas altera o array de origem. + Soma dois arrays, criando um novo com os itens de ambos. Subtrai dois arrays, criando um novo com os itens do primeiro no contidos no segundo. push Adiciona um item no final do array. pop Retorna o ltimo item do array e o remove do array. find Recebe um bloco com um parmetro e retorna o primeiro item para o qual o bloco retornar verdadeiro. clear Remove todos os itens do array. shift Retorna o primeiro item do array e o remove do array. first Retorna o primeiro item do array. Recebe um valor inicial e um bloco com dois parmetros. O primeiro o valor atual, e o segundo, o inject item atual do array, retorna o resultado da operao realizada no bloco. O prximo exemplo utiliza o mtodo inject para somar todos os itens de um array numrico. intro/28inject.rb
1 2 3 4 5 arr = [1, 2, 3, 4, 5, 6] v = arr.inject(0) do |val, it| val + it end puts v

Existe ainda mais uma forma de criar um array no Ruby, que serve para criar mtodos com uma lista varivel de parmetros. Para isso, basta declarar o ltimo parmetro de um mtodo com o nome *nome, de forma que esse parmetro seja um array contendo todos os parmetros no declarados passados ao mtodo, como pode ser visto no exemplo a seguir. intro/29varargs.rb
1 2 3 4 5 6 7 8 9 10 11 def parametros_variaveis(*arr) if arr arr.each do |v| print "#{v.class} - #{v}\n" end end end parametros_variaveis parametros_variaveis 1, "asda", :simb, :a => "teste", :arr => %w{a b c}

Hashes
Hashes representam outra construo bastante utilizada no cdigo Ruby. Utilizaremos muitos hashes no cdigo Rails que ser escrito nos prximos captulos. Hashes so semelhantes a arrays, mas no so simples colees de objetos: so colees do tipo chave=valor. Eles so to comuns no cdigo Ruby que existe at um operador especial para declarar hashes, que o =>, que significa associado, ou seja, o valor esquerda est associado ao valor direita. Existem duas formas de se declarar um hash. A primeira utilizando o atalho {}, e a segunda, utilizando o construtor da classe Hash, como no exemplo a seguir: intro/30hashes.rb

1 2 3 4

h = h1 = h2 = puts

{1 => "asda", "b" => 123} {} Hash.new h.methods.sort

Hashes tambm tm alguns mtodos que podem facilitar muito a vida dos programadores Ruby como pode ser visto na tabela abaixo. Mtodo [] []= each each_key each_value has_key? has_value? Descrio Retorna o valor da chave passada como parmetro. Atribui o valor da chave. Executa um bloco com dois argumentos para cada posio do mapa. Executa um bloco com um argumento (a chave) para cada posio do mapa. Executa um bloco com um argumento (o valor) para cada posio do mapa. Retorna verdadeiro se a chave existe no mapa. Retorna verdadeiro se o valor corresponde a alguma das chaves do mapa. Possibilita configurar qual valor o mapa vai retornar quando for buscado o valor para uma chave default= inexistente. default_proc Idem a default=, mas executa um bloco para criar o valor para as novas chaves. delete Remove o item correspondente chave indicada do mapa, retornando o valor da chave.

Smbolos
Smbolos, no Ruby, so aqueles nomes malucos que comeam com : por todo o cdigo. So muito utilizados como chaves em hashes e em quaisquer lugares onde voc precisar de um rtulo (label) para alguma coisa. Eles so basicamente strings, mas ocupam muito menos processamento do interpretador Ruby e muito menos memria do que strings normais. Strings podem ser transformadas em smbolos utilizando o mtodo to_sym. Sempre que for definir chaves em hashes que serviro como nomes de parmetros a mtodos, ou precisar enviar uma mensagem a um objeto, um smbolo sempre melhor do que uma string, pois utilizar muito menos memria, o que far com que sua aplicao gaste menos recursos e se comporte de maneira mais socivel com o computador.

Expresses regulares
Expresses regulares consistem na forma mais fcil de extrair informaes de um texto ou alterar textos com padres razoavelmente complexos. O Ruby tem duas formas de declarar uma expresso regular e diversos mtodos que recebem expresses regulares como parmetros. Uma coisa a ser lembrada, e que facilita muito a vida dos programadores Ruby, que expresses regulares fazem parte da linguagem no Ruby. Isso facilita muito seu uso em comparao s linguagens em que expresses regulares so implementadas em forma de uma biblioteca externa. As trs formas de declarar uma expresso regular no Ruby so /ER/, %r{ER} ou por meio do mtodo new da classe Regexp, como no exemplo a seguir: intro/31regexp.rb
1 2 3 4 5 6 7 8 9 er = er = er = er = puts puts puts puts puts /(.*?) .*/ %r{(.*?) .*} Regexp.new "(.*?) .*" /^[0-9]/ "123" =~ er er =~ "123" er =~ "abc" er !~ "123" er !~ "abc"

10 11 12 13 14 15 16 17 18 19 20 21 22 23

mt = /(..)\/(..)\/(....)/.match("12/05/2000") puts mt.length puts mt[0] puts mt[1] puts mt[2] puts mt[3] todo, dia, mes, ano = *(/(..)\/(..)\/(....)/.match("12/05/2000")) puts todo puts dia puts mes puts ano puts "Urubatan".gsub(/ru/, "RU") re = /.*/ puts re.methods.sort

Toda expresso regular uma instncia da classe Regexp e, da mesma forma que os nmeros, a classe Regexp disponibiliza diversos mtodos e operadores para facilitar as operaes com expresses regulares, como podemos ver no exemplo a seguir. Alguns mtodos importantes disponveis na classe Regexp so: Mtodo Descrio =~ Procura pela expresso regular no texto e retorna o ndice em que ela foi encontrada. !~ Informa se existe uma ocorrncia da expresso regular no texto. Retorna um objeto do tipo MatchData, que contm ponteiros para os locais onde cada grupo da match expresso regular foi encontrado. O operador * do Ruby utilizado no exemplo, quando usado em um array, expande o array em variveis. Dessa forma pode-se atribuir um array a uma quantidade de variveis igual s posies do array. O mtodo gsub da classe String demonstrado faz substituio de texto utilizando expresses regulares. possvel utilizar grupos na substituio, tornando o mtodo ainda mais flexvel.

Classes e mtodos
Classes representam uma das bases da orientao a objetos no Ruby. Tudo no Ruby um objeto, e todo objeto no Ruby instncia de uma classe. Por exemplo, 1 uma instncia da classe Fixnum, e todos os mtodos dessa classe podem ser chamados nessa instncia. Assim, classes tambm so objetos no Ruby, portanto, podem ter mtodos prprios, ou seja, possvel definir mtodos de classe, diferentemente do Java ou do C++, que tm mtodos estticos. Mtodos de classe so herdados por classes descendentes da classe onde foram definidos e podem saber a qual objeto pertencem, pois nessa situao a palavra-chave self vai apontar para a classe e no para uma de suas instncias. Para definir uma classe, usada a palavra-chave class, seguida por um nome de uma constante, que ser utilizado para referenciar aquela classe. Variveis de instncia so definidas por meio da nomenclatura @nome e variveis de classe @@nome, mas se o seu cdigo-fonte contiver muitas variveis de classe, h um srio problema de design. Vejamos alguns exemplos para facilitar o entendimento: intro/32class.rb
1 class Carro 2 def initialize(fabricante, modelo, ano) 3 @fabricante = fabricante 4 @modelo = modelo 5 @ano = ano 6 end 7 8 attr_accessor :fabricante, :modelo, :ano 9 end 10 clio = Carro.new "Renault", "clio", "2000"

11 puts clio.modelo

Herana um dos pilares da orientao a objetos (os outros dois so encapsulamento e polimorfismo). O Ruby suporta herana utilizando o operador < na definio de uma classe.

intro/33inheritance.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 require '32class' class Clio < Carro @@fabricante = "Renault" @@modelo = "clio" def initialize(ano) super(@@fabricante, @@modelo, ano) end end clio = Clio.new(2003) puts clio.modelo

Mtodos de classe so bastante teis no Ruby, pois podem saber a que classe pertencem. Para simplificar o exemplo, podemos tambm utiliz-los para criar uma fbrica de carros: intro/34classmethod.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 require '33inheritance' class Fabrica def self.clio Clio.new(2003) end def self.megane Carro.new "Renault", "megane", 2003 end end puts Fabrica.clio.inspect puts Fabrica.megane.inspect

Como foi possvel perceber, para criar um mtodo de classe usada a notao self.mtodo. possvel definir novos mtodos em classes a qualquer momento, bem como definir novos mtodos apenas em uma instncia de uma classe, o que internamente vai fazer com que uma nova classe annima seja criada apenas para aquele objeto. Classes tm alguns mtodos interessantes para entendermos o cdigo Rails que ser usado nos prximos captulos. A seguir, veja uma breve lista. Mtodo class class_eval class_variable_defined? class_variables const_defined? Descrio Retorna a classe de um objeto. Executa uma string contendo cdigo-fonte Ruby no contexto da classe. Informa se uma varivel est definida nessa classe. Lista todas as variveis de classe. Informa se existe uma constante definida na classe.

const_get const_set constants instance_eval instance_methods

L o valor de uma constante. Grava o valor em uma constante ou cria uma nova. Lista todas as constantes definidas na classe.
Executa uma string contendo cdigo-fonte Ruby no contexto de uma instncia da classe.

Lista todos os mtodos de instncia da classe. instance_variable_defined? Informa se uma varivel est definida para as instncias da classe. instance_variable_get L o valor de uma varivel de instncia. instance_variable_set Cria ou altera o valor de uma varivel de instncia.

Mtodos
Uma coisa interessante sobre mtodos no Ruby que eles no existem. exatamente isso: no h mtodos em Ruby! A diferena bastante sutil, mas ajuda a entender melhor como as coisas funcionam. No Ruby no se chama um mtodo de objeto: envia-se uma mensagem para um objeto, e esta pode ter parmetros, mas sempre tem um retorno. como se cada objeto tivesse uma caixa de correio interna, que s aceita mensagens para destinatrios conhecidos, e todos os destinatrios desconhecidos vo para o mesmo lugar: uma caixa com o nome de method_missing. Isso permite que mtodos inexistentes sejam adicionados apenas no momento em que se tornam necessrios. Veremos isso acontecer bastante no cdigo do Rails, cuja leitura recomendo aps a concluso deste livro, pois a melhor forma de entender profundamente como o Rails funciona lendo o cdigo-fonte do Rails. Aqui est um exemplo de utilizao do method_missing: intro/35method_missing.rb
1 2 3 4 5 6 7 8 class Teste def method_missing(method, *args)

print "Mtodo #{method} chamado na classe Teste, com os argumentos #{args.join(', ')}\n"

end end t = Teste.new t.imprimir t.qualquer_coisa 1, 2, 3, "asd", :teste => 1

No considerada uma boa prtica utilizar o method_missing o tempo todo, principalmente porque, no exemplo mostrado, se fosse feita a pergunta t.respond_to? :imprimir, o objeto diria que no responde mensagem, mas ela seria enviada. Tudo funciona sem problemas, o que cria um objeto com comportamento inconsistente. Uma melhor abordagem seria a utilizao do define_method para criar uma caixa de correspondncias, no momento em que esta se tornar necessria, da forma como o attr_accessor faz. Para demonstrar isso, criaremos um mtodo que define propriedades em um objeto, semelhante ao attr_accessor. Para tal, vamos utilizar o mdulo que assunto da prxima seo. intro/36define_method.rb
1 module Propriedades 2 def propriedade(nome) 3 ivarname = "@#{nome}".to_sym 4 self.send :define_method, nome do 5 self.instance_variable_get ivarname 6 end 7 self.send :define_method, "#{nome}=".to_sym do |val| 8 self.instance_variable_set ivarname, val 9 end 10 end 11 end 12 13 class Teste 14 extend Propriedades

15 16 17 18 19 20

propriedade :nome end t = Teste.new t.nome="urubatan" print t.inspect print "\n"

Mdulos
Mdulos no Ruby so repositrios de coisas. Essa foi a melhor explicao de mdulos que consegui, falando de uma forma bem genrica. Eles podem conter classes, sendo usados como pacotes de classes para organizar um domnio muito grande. Ou podem conter mtodos para serem utilizados como mixins, um conceito bastante interessante que, utilizado junto com as classes abertas, parcialmente responsvel por toda a flexibilidade do Ruby. Para utilizar mdulos como organizadores de classes, basta fazer como neste exemplo: intro/37modules.rb
1 module Administracao 2 class Cliente 3 attr_accessor :nome 4 5 def initialize 6 @nome = "" 7 end 8 end 9 end

Utilizar mtodos como mixins bastante semelhante ao exemplo anterior, mas dentro do mdulo so definidos mtodos, e no classes, como no exemplo a seguir. intro/38modulemixin.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class Teste def ola_mundo print "ola mundo\n" end def self.ola_mundo print "ola mundo da classe\n" end end Teste.ola_mundo t = Teste.new t.ola_mundo module MixinTest def self.included(base) base.send :include, InstanceMethods base.send :extend, ClassMethods end module ClassMethods def metodo_de_classe print "Novo mtodo de classe definido no mdulo 'ClassMethods'\n" end end module InstanceMethods def metodo_de_instancia print "Novo mtodo de instncia definido no mdulo 'InstanceMethods'\n" end end end class Teste include MixinTest

32 end 33 Teste.metodo_de_classe 34 t.metodo_de_instancia

Em qualquer classe, pode-se chamar o mtodo include passando um mdulo como parmetro, e os mtodos desse mdulo estaro disponveis para todas as instncias dessa classe. Se o mtodo extend for utilizado, os mtodos do mdulo estaro disponveis para a classe e no para suas instncias. O mtodo send utilizado no exemplo envia uma mensagem para um objeto. No caso, o objeto era a classe Teste.

Operadores condicionais e loops


Ruby uma linguagem dinmica, mas tambm imperativa, e todas as linguagens imperativas tm estruturas de controle de fluxo e loop. Nas prximas sees veremos quais estruturas desse tipo o Ruby contm e como utilizlas.

If / elsif / else / end


A estrutura if utilizada para executar um conjunto de instrues. Se a condio for verdadeira, no necessrio um then, e o if pode ser utilizado no final de uma instruo tambm. Dessa forma, o bloco anterior de cdigo s ser executado se a condio for verdadeira. intro/39ifelse.rb
1 2 3 4 5 6 7 8 9 10 a = 0 if a==0 print "zero" elsif a==1 print "um" else print "no sei que nmero este" end b = 5 if a!=1 puts b

unless else end


O unless um atalho, mais fcil de ler para um if not em ingls. Ele facilita a leitura do cdigo quando utilizado corretamente, mas semanticamente um if not e pode ser utilizado tambm no final de uma sentena da mesma forma que o if. intro/40unlesslseend.rb
1 2 3 4 5 6 7 8 9 10 a = 1 unless a==0 print "no else print "a end b = 6 unless puts b b = 7 unless puts b

zero\n" zero\n" b b

Como pode ser visto no exemplo, o unless pode ser utilizado para definir o valor de uma varivel apenas se ela ainda no tiver um valor. necessrio apenas tomar cuidado com essa abordagem se o valor esperado um valor booleano.

case / when / else / end


Case um atalho mais organizado e semntico para uma sequncia de elsif. O comando case do Ruby bastante flexvel, mais do que em Java ou C++, por exemplo. Isso porque no Ruby ele pode ser utilizado com qualquer tipo de objeto e no apenas com nmeros. S no possvel misturar objetos, como pode ser visto no exemplo a seguir.

intro/41casewhenelse.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 a = 5 case a when 1..3 puts "a entre 1 e 3\n" when 4 puts "a=4\n" else puts "nenhuma das anteriores\n" end a = "b" case a when "a" puts "a\n" when "b" puts "b" else puts "outra letra" end

Operadores de loop
Os operadores apresentados nesta seo podem ser utilizados com qualquer um dos loops que sero apresentados nas prximas sees: Operador break next return redo Sai do loop atual. Executa o prximo passo do loop. Sai do loop e do mtodo atual. Reinicia o loop atual. Descrio

while
O while um loop bastante flexvel, pois permite o controle da condio do loop, podendo ser utilizado com qualquer condio booleana, derivada da comparao de qualquer tipo de objeto. intro/42while.rb
1 i = %w{a b c d e f} 2 while b=i.pop 3 puts b 4 end

No exemplo, o while foi utilizado para iterar sobre um array de strings. Pense nisso apenas como um exemplo, pois neste caso o mais indicado seria utilizar o mtodo each da classe Array.

for
O lao for utilizado para repetir um bloco de cdigo por um nmero conhecido de vezes. Utilize-o apenas quando for realmente necessrio, pois o modo padro do Ruby de iterar sobre colees empregando os mtodos apropriados, como o each, por exemplo.

intro/43for.rb
1 2 3 4 5 6 for i in 1..5 puts i end for a in %w{a b c d} puts a end

until
O bloco until o contrrio do while: ele repete o bloco de cdigo at que a condio seja verdadeira. intro/44until.rb
1 i=5 2 until i==0 3 puts i 4 i -=1 5 end

begin
O bloco begin utilizado em conjunto com o while ou until quando se deseja que o bloco seja executado pelo menos uma vez. Assim, a condio fica no final do bloco e no no incio, como nos exemplos anteriores. intro/45begin.rb
1 i=-5 2 begin 3 puts i 4 i+=1 5 end while i < 0

Nesse exemplo, se um while padro fosse utilizado, o bloco no teria sido executado nenhuma vez.

loop
O lao loop o lao mais flexvel. Ele ser executado at que encontre um comando break ou return no bloco. intro/46loop.rb
1 loop do 2 puts "a" 3 break if true 4 end

Padres importantes
muito importante quando se aprende uma linguagem nova no tentar programar na linguagem anterior com a sintaxe da linguagem nova. Para isso, importante aprender alguns padres bastante utilizados no Ruby. H uma pequena lista de coisas que devem ser lembradas a seguir.

Nomes de arquivos
Nomes de arquivos utilizam letras minsculas e sublinhado para separar palavras. Um arquivo .rb que contm a definio de uma classe de nome ClienteEspecial ter o nome cliente_especial.rb. Um mdulo segue o padro de nomenclatura de classes e, na maioria, dos casos tambm define a estrutura de diretrios. Seguindo o exemplo, se a classe ClienteEspecial estiver definida dentro do mdulo Clientes, o arquivo cliente_especial.rb estar dentro do diretrio clientes.

O Ruby no impe esses padres. possvel definir todas as classes da aplicao no mesmo arquivo se desejado, mas a maior parte das aplicaes Ruby segue padres parecidos com os descritos.

Classes, atributos e mtodos de acesso


No obrigatrio o nome de uma classe comear com uma letra maiscula, mas bastante recomendado, pois dessa forma tambm se define uma constante que apontar para a classe, facilitando seu uso. Algumas vezes necessrio criar mtodos de acesso para variveis de instncia da classe. O prprio attr_accessor faz exatamente isso. Mtodos de leitura de uma varivel de instncia tm o mesmo nome da varivel, sem o caractere @ no incio, e mtodos de escrita tm o mesmo nome terminado em =. intro/47standards.rb
1 2 3 4 5 6 class Teste attr_accessor :nome end t = Teste.new puts t.methods.sort

Nomenclatura de mtodos
Nomes de mtodos no Ruby tm sempre todas as letras minsculas e utilizam sublinhado _ para separar palavras. Mtodos que transformam um objeto em outro tem o nome iniciado por to_, como, por exemplo: Mtodo to_s Transforma em String. to_i Transforma em Fixnum. to_a Transforma em Array. to_sym Transforma em um smbolo. Lembre-se disso ao criar esse tipo de mtodo. E para quem quiser mais informaes, acredito qe todos os que leram at aqui, a pgina de documentao do site da linguagem tem bastante coisa: http://www.ruby-lang.org/pt/documentacao/. Descrio