Lembro que sempre que falava com alguém sobre Ruby a conversa era mais ou menos assim:

– Cara, Ruby é muito foda, é uma linguagem totalmente orientada à objetos.
– Bro, tem infinitas linguagens orientadas à objetos…
– Não, você não tá ligado, em Ruby TUDO é objeto, você consegue sobrescrever qualquer coisa.
– Tá, em Java tem override, eu consigo sobrescrever coisas, o que é que tem demais nisso? – Não cara, em Ruby tudo MESMO é um objeto, números são objetos, eu consigo fazer o sinal de + virar – !
– E alguém iria querer fazer o + virar – ? Como assim números são objetos? Números são números, para de falar besteira bro…

E aí ficava por isso mesmo. E o engraçado é que sempre que vejo alguém falar sobre como Ruby é legal, acaba saindo esse “consigo fazer o sinal de + virar – !”. E é claro, ninguém vê sentido ou utilidade nisso. Vou tentar mostrar então o que isso significa e que sim, isso é bem legal!

Como assim tudo é objeto e pode ser manipulado?

Um número em Ruby é um objeto, ou seja, possui uma classe como qualquer outro objeto no nosso código. Podemos ver isso com:

[sourcecode language=”ruby”]
2.class
[/sourcecode]

Isso retornará:

Fixnum

Em Ruby, core classes, que são classes bases da linguagem podem ser alteradas como qualquer outra de forma simples. E, o + não tem nada de especial, é apenas um método da classe, logo, o exemplo que tanto falam pode ser feito da seguinte maneira:

[sourcecode language=”ruby”]
class Fixnum
def +(value)
self – value
end
end

puts 5 + 1
[/sourcecode]

Tal código escreverá 4, pois agora o + significa menos. Para esclarecer rapidamente, basta entender que o mesmo código acima pode ser escrito como:

[sourcecode language=”ruby”]
5.+(1)
[/sourcecode]

Ou seja, + é apenas um método do objeto 5 que está recebendo o parâmetro 1.

Para ilustrar um pouco mais, poderíamos fazer algo como:

[sourcecode language=”ruby”]
class Fixnum
def mais(value)
self + value
end
end

cinco = 5
um = 1

puts cinco.mais(um)

puts cinco + um
[/sourcecode]

Tal código retornará:

6
6

Percebe como tudo é objeto e por conta disto pode ser facilmente manipulado em Ruby? Vamos dar um exemplo de como isso poderia se tornar algo útil e interessante.
Sabemos que uma semana tem 7 dias, se queremos somar semanas para ver quantos dias temos, podemos fazer os números responderem isso. Confuso? Vejamos:

[sourcecode language=”ruby”]
class Fixnum
def semana
self * 7
end

def semanas
self * 7
end
end

puts 2.semanas
puts 1.semana
puts 2.semanas + 1.semana
[/sourcecode]

O resultado:

14
7
21

Interessante, não? Isso é a base do que acontece quando utilizamos Ruby on Rails e passamos a contar com certas comodidades ao poder utilizar coisas como 2.weeks, por exemplo.

E se podemos manipular números, podemos fazer o mesmo com qualquer coisa, inclusive com textos. Vamos alterar a classe String e decidir que agora todo texto que chamar o método come_o_cogumelo vai ficar com suas letras em maiúsculo:

[sourcecode language=”ruby”]
class String
def come_o_cogumelo
self.upcase
end
end

puts "mario".come_o_cogumelo
[/sourcecode]

Isso irá retornar:

MARIO

Tudo é objeto, tudo é manipulável.

Como fazer Métodos “Inteligentes”

Outra coisa que existe em Ruby também é um tal de method_missing, com ele você consegue interceptar em uma classe todo método que é chamado e não existe, um exemplo do que é possível fazer:

[sourcecode language=”ruby”]
joao = Pessoa.new

joao.bolso < 50.dinheiros

joao.bolso < 10.dinheiros

joao.bolso – 20.dinheiros

puts joao.tem_dinheiro_ai_bro? # tenho 40 reais cara…

puts joao.me_da_20_reais! # blz, pega 20 reais…

puts joao.quero_mais_30_reais_emprestados! # blz, pega 30 reais…

puts joao.sobrou_quanto_de_grana? # tenho -10 reais cara…
[/sourcecode]

Sim, conseguimos fazer um objeto se comportar exatamente dessa forma. Manipulamos a classe Fixnum para existir o método dinheiros, criamos o método < na classe Pessoa para “jogar” dinheiro dentro do bolso dela e com o método method_missing na classe Pessoa, capturamos todas as perguntas e afirmações feitas que não existem de fato na classe, as identificamos e interpretamos utilizando Expressões Regulares (você pode ler mais sobre elas aqui) e fazemos o que acreditamos que o usuários quis dizer com aquilo:

[sourcecode language=”ruby”]
class Fixnum
def dinheiros
self
end
end

class Pessoa
def initialize
@reais = 0
end

def bolso
self
end

def &amp;amp;amp;lt;(reais)
@reais += reais
end

def -(reais)
@reais -= reais
end

def method_missing(method_name, params = nil)
if method_name =~ /[grana|dinheiro].*\?/
puts "tenho #{@reais} reais cara…"
elsif method_name =~ /[da|quero].*\d.*\!/
@dinheiro_emprestado = method_name.to_s.scan(/\d{1,}/).first.to_i
@reais -= @dinheiro_emprestado
puts "blz, pega #{@dinheiro_emprestado} reais…"
end
end
end
[/sourcecode]

Você pode ver o código sendo executado em: http://ruby.gbaptista.com/p/jeyI4A 

Tudo bem, o código ficou bem ruim e feio e, além disso, despejei infinitos conceitos complexos, todos de uma vez para você. Com calma é possível pesquisar e estudar cada detalhe… A ideia foi mostrar como você realmente consegue manipular tudo em Ruby, criando qualquer coisa.

Somando Cores

Um outro exemplo um pouco mais simples, e se quiséssemos somar cores primárias para ver o resultado? Exemplo: Azul + Amarelo = Verde.

Podemos manipular a classe String:

[sourcecode language=”ruby”]
class String
alias :original_sum :+

COLORS = {
‘azul+amarelo’ =&amp;amp;gt; ‘verde’,
‘amarelo+azul’ =&amp;amp;gt; ‘verde’,
‘vermelho+amarelo’ =&amp;amp;gt; ‘laranja’,
‘amarelo+vermelho’ =&amp;amp;gt; ‘laranja’,
‘azul+vermelho’ =&amp;amp;gt; ‘violeta’,
‘vermelho+azul’ =&amp;amp;gt; ‘violeta’
}

def +(value)
new_color = COLORS["#{self.downcase}+#{value.downcase}"]

if new_color
new_color
else
self.original_sum(value)
end
end
end
[/sourcecode]

E agora, basta somar as cores:

[sourcecode language=”ruby”]
puts "Azul" + "Amarelo"

puts "Amarelo" + "Vermelho"

puts "Vermelho" + "Azul"

puts "lorem " + "ipsum"
[/sourcecode]

O resultado:

verde
laranja
violeta
lorem ipsum

E assim temos infinitas possibilidades por conta da flexibilidade da linguagem.

O Dark Side da Mágica

Nessa vida, nem tudo são flores. Essa possibilidade de manipular qualquer coisa de forma tão simples abre um leque de infinitas possibilidades ao trabalhar com a linguagem… Porém, tal possibilidade abre uma porta que pode nos levar à caminhos perigosos como por exemplo exagerar na utilização de Monkey PatchO Pablo tem um post bem legal que explica o que eles são e como utilizá-los de forma consciente, dá uma olhada lá! > Monkey Patch – Sim, não, quando?

E falando em Ruby, nos dias 23 e 24 de Setembro, acontece na Fecomercio em São Paulo, o RubyConf Brasil 2016! Serão 2 dias de evento, com mais de 80 palestrantes e com 5 trilhas sobre diversos assuntos além de Ruby, para você que deseja aprender e atualizar seus conhecimentos sobre Ruby on Rails, Devops, JavaScript, Elixir, Clojure, Go, Rust, Crystal e outras linguagens de programação. Não fique de fora do maior evento de Ruby da América Latina, inscreva-se aqui no RubyConf Brasil!