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:
- Aqui temos um array de 10 elementos e dividimos por 2, retornando vários arrays com 2 elementos.
- 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!).
- 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
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.
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







Comentários Recentes