MouseOver Studio

MouseOver Studio header image 2

Traduz teus objetos entre Ruby e Java com Rhyme

setembro 29th, 2008 por Diego Carrion · 4 comentários

O problema

Quando trabalhamos com JRuby é muito provável que tenhamos objetos de Ruby ou de Java e que queiramos chamar algum método da outra linguagem que esteja esperando um objeto de uma classe similar nessa linguagem.

Isso acontece mesmo?

Um claro exemplo do problema acontece no Liquid4j, que foi apresentado no ultimo post. Na oportunidade mencionei que o Liquid4j conta com um método em Java chamado de render que recebe um objeto do tipo java.util.HashMap com as chaves e valores do template a ser renderizado. Também mencionei que por detrás dos panos o método utiliza o JRuby para chamar um método Ruby chamado igualmente de render. O problema é que esse ultimo método espera um objeto do tipo Hash, pelo que o processo seria similar a realizar o seguinte:

require "rubygems"
require "liquid"
map = java.util.HashMap.new
Liquid::Template.parse("hi").render(map)

que resultaria em:

Liquid::ArgumentError: Expect Hash or Liquid::Context as parameter

O que aconteceu?

Liquid é um livraria feita unicamente para Ruby e por tanto trabalha com objetos Ruby, ela não sabe trabalhar com objetos Java. Liquid4j é uma livraria feita unicamente para Java, ela utiliza o JRuby mas à nível da API tudo acontece em Java: métodos e objetos. Se Liquid4j chamasse o método render do Liquid com o objeto que recebeu como parâmetro, Liquid não iria reconhecer o tipo dele, pelo que nao iria saber como trabalhar com ele e por isso iria lançar a excepção mostrada.

“Ja chamei métodos Ruby a partir do Java e vice-versa e não precisei converter/traduzir nada!”

Existem alguns tipos de objetos que são convertidos automaticamente. Esses tipos são os tipos primitivos, como pode ser conferido aqui.

Por que JRuby não converte então automaticamente outros tipos de objetos?

Não seria uma boa idéia, porque por exemplo eu poderia querer criar uma função em Ruby que trabalhasse com o tipo java.lang.ArrayList.

A solução

Criei uma gem chamada Rhyme que se encarrega de traduzir objetos entre Ruby e Java. Rhyme traduz o objeto passado como parâmetro no método translate, assim como todos os objetos dentro dele. Isso quer dizer que se por exemplo a gente tiver um objeto do tipo Array que tiver um Hash num dos índices e aquele Hash tiver diferentes objetos nas diferentes keys, todos os objetos a partir do Array irão ser traduzidos para a contraparte em Java, como mostra o seguinte exemplo:

dcrec1:rhyme dcrec1$ jirb
irb(main):001:0> require "rubygems"
=> true
irb(main):002:0> require "rhyme"
=> true
irb(main):003:0> Rhyme.translate([{ "date" => Date.new}])[0]["date"].class
=> Java::JavaUtil::Date

Utilizacão

Se estivermos no Ruby, precisaremos incluir a gem Rhyme no nosso código e interpretar ele com JRuby:

require "rubygems"
require "rhyme"
...
java_obj = Rhyme.translate(ruby_obj)

Por outro lado, se estivermos programando em Java, precisaremos alem do engine do JRuby, os helpers em Java para o Rhyme. O código poderá então ser executado assim:

import com.mouseoverstudio.rhyme.Rhyme;
...
Object rubyObject = Rhyme.translate(javaObject)

Onde encontrar o helper do Java? Como contribuir?

As fontes do projeto estão hospedadas no GitHub. Caso queiram trabalhar com Java e nao estejam a fim de compilar as fontes, existe um jar disponível na pasta dist. As dependências para o helper em Java podem ser encontradas na pasta lib.

Tags: java · jruby · rhyme · ruby

4 respostas ate agora ↓

  • 1 Leandro // set 29, 2008 at 10:58 am

    Outro? Rapaz, tá precisando dormir, hein? Passar a noite em claro todo dia faz mal!

    kkkkk

    Brincadeira! :)

  • 2 Diego Carrion // set 29, 2008 at 11:07 am

    Hahahahah ainda falta um, so falta escrever o post.

    Mas depois de esse ja paro, to precissando ir dormir mais cedo mesmo 😛

  • 3 Shairon Toledo // out 1, 2008 at 2:01 pm

    Gosto dessas coisas!! Parabéns pelo não trivial post!

  • 4 Diego Carrion // out 1, 2008 at 2:14 pm

    Obrigado Shairon :)

Deixar um comentário