You are currently browsing the category archive for the ‘Ruby’ category.

Palavras-chave: Ruby, código fonte, ruby2ruby

Podemos obter o código de um método como uma String usando a gem ruby2ruby:

require "rubygems"
require "ruby2ruby"

class Teste
   def metodo
      puts "oi!"
   end
end

teste = Teste.new
metodo = teste.method(:metodo)
puts metodo.to_ruby

Rodando o código:

$ ruby r2r.rb
def metodo
  puts("oi!")
end

Vale mencionar que isso só funciona nos métodos de uma instância.

Palavras-chave: Ruby, array

Para contar a frequência com que os valores de um array se repetem, podemos utilizar:

array = %w(morango abacaxi banana morango pera morango abacate banana)
p array.inject(Hash.new(0)) {|memo,value| memo[value] += 1; memo}

Será retornada uma hash com os valores como chave e a frequência de repetição como valores.

O segredo é usar uma hash com valor default e retorná-la no final do bloco do inject. Rodando o programa vamos ter:

{"banana"=>2, "abacate"=>1, "pera"=>1, "abacaxi"=>1, "morango"=>3}

Palavras-chave: Ruby, array, divide

Suponha que você tenha um array de X elementos e precise dividi-lo em arrays com Y elementos cada. A flexibilidade de Ruby nos permite definir operadores novos para as classes, então vamos criar um operador de dividir (/) para a classe Array:

class Array
   def / len
     inject([]) do |ary, x|
       ary << [] if [*ary.last].nitems % len == 0
       ary.last << x
       ary
     end
   end
end

Vamos rodar agora com alguns arrays para ver o que aconteceu:

p (1..10).to_a / 2
=> [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
p %w(hiro ando nikki jessica sylar) / 2
=> [["hiro", "ando"], ["nikki", "jessica"], ["sylar"]]
p (1..10).to_a / 4
=> [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10]]

Vamos analisar cada caso:

  1. Aqui temos um array de 10 elementos e dividimos por 2, retornando vários arrays com 2 elementos.
  2. Aqui temos um array ímpar de 5 elementos que dividimos por 2, retornando dois arrays com 2 elementos e um último com apenas um elemento (deixa aquele cara longe!).
  3. Aqui temos um array de 10 elementos que é dividido por 4, retornando dois arrays com 4 elementos e um último array com 2 elementos.

Ou seja, sempre que o resultado da divisão não for exata, temos o resto no último elemento retornado. As expressões que usei acima do tipo (1..10).to_a nada mais fazem do que converter uma Range em um Array.

O código do método “/” é meio críptico, mas se eu tentar explicar aqui vai ficar meio comprido e vou levar uma bronca, então dêem uma queimada nos neurônios aí. ;-)

Palavras-chave: Ruby, método, nome, corrente, method, current

Se você quiser saber o nome do método onde se encontra, terá que criar um outro método que quando chamado descubra o nome do método que o chamou. Assim:

class MinhaClasse
	def self.nome_do_metodo
		caller.first
	end
	def self.meu_metodo
		puts "Estou no método '#{nome_do_metodo}'"
	end
end
MinhaClasse.meu_metodo =>
    Estou no método 'method_name.rb:6:in `meu_metodo''

No retorno acima, veio o nome do arquivo “method_name.rb” e logo após, o nome do método de onde imprimi a mensagem: “meu_metodo”.

Usando expressões regulares é possível filtrar essa mensagem, para torná-la mais amigável. Como Ruby permite que alteremos até as classes básicas da linguagem (dê um tiro no pé apenas se você quiser!), vamos gerar um método do Kernel para que possamos usá-lo globalmente:

module Kernel
	def nome_do_metodo
		caller.first =~ /`([^']*)'/ and $1
	end
end

class MinhaClasse
	def self.meu_metodo
		puts "Estou no método '#{nome_do_metodo}'"
	end
end

class OutraClasse
	def self.meu_outro_metodo
		puts "Estou no método '#{nome_do_metodo}'"
	end
end
MinhaClasse.meu_metodo => Estou no método 'meu_metodo'
OutraClasse.meu_outro_metodo => Estou no método 'meu_outro_metodo'

Explicando:

A chamada em caller.first retorna de onde o método foi chamado (justamente o método que queremos saber o nome), e compara com a expressão regular para ver se achou algum nome de método no final.

Ali é feito um “curto-circuito” onde é testado se a expressão regular “casou”, fazendo um and lógico com a última condição avaliada, que no caso, é $1.

Esse $1 é a primeira variável de Ruby que traz o conteúdo que “casou” da expressão regular. Se não casou, a segunda parte do and nem é avaliada e é retornado nil. Se casou, é retornada a parte que casou, que nesse caso, é o nome do método que queremos.

Palavras-chave: Ruby, Fixnum, object_id

Uma jogada legal com objetos do tipo Fixnum em Ruby é descobrir o valor do objeto através do seu object_id, fazendo um simples deslocamento binário:

n = 123456
n.object_id >> 1
=> 123456

Veja outra dica sobre object_id em Ruby.

Palavras-chave: Ruby, Fixnum, object_id

Em Ruby podemos facilmente verificar se um objeto é da classe Fixnum através do seu object_id (os números podem variar):

s = "oi"
s.object_id
=>  -605527578
n = 123456
n.object_id
=> 246913
s.object_id & 0x1
=> 0
n.object_id & 0x1
=> 1

Fazendo um and com o object_id e 0×1, somente os objetos da classe Fixnum irão retornar 1.

Veja uma outra dica sobre object_id em Ruby.

Palavras-chave: ruby, array, hash, splat

Podemos converter facilmente um array com um número de elementos pares para uma hash da seguinte maneira:

array = %w(um 1 dois 2 tres 3)
hash  = Hash[*array]
p hash

Executando o código:

{"tres"=>"3", "um"=>"1", "dois"=>"2"}

Convém prestar atenção no *, que nesse caso recebe o apelido carinhoso de operador splat. Ele vai “abrir” o array para o método [] da hash.

Se esquecermos de usar o * o método vai reclamar dizendo que recebeu um valor ímpar para a hash (e recebeu mesmo, apenas um array).

Palavras-chave: Ruby, hash, default, blocos

Em Ruby podemos permitir que um valor default seja retornado na tentativa de acesso à um elemento que não existe ainda em uma hash, dessa maneira:

hash = Hash.new(0)
puts hash["abobora"]
0
puts hash["batata"]
0

Mais interessante ainda é criarmos o valor de um elemento que não existe através da execução de um bloco de código. Vamos supor que queremos uma hash que contenha a data de criação de domínios, a qual terá como chave a URL do domínio e a data de criação como valor, retornado após uma consulta à uma determinada URL:

require "open-uri"

hash = Hash.new do |hash,url|
    html = open("http://reports.internic.net/cgi/whois?
whois_nic=#{url}&type=domain").read
    hash[url] = html.grep(/Creat/i).join.split(/:/,2)[1].strip.chomp
end

hash["eustaquiorangel.com"]
hash["codare.net"]
hash["ruby-lang.org"]
hash.each {|url,date| puts "#{url}: #{date}"}

O resultado será:

codare.net: 19-sep-2006
ruby-lang.org: 16-Sep-1999 09:28:50 UTC
eustaquiorangel.com: 13-jul-2006
Add to Technorati Favorites

Assuntos