Skip to content

Instantly share code, notes, and snippets.

@sebglazebrook
Last active May 11, 2018 05:15
Show Gist options
  • Select an option

  • Save sebglazebrook/9ac4aac479db58ac9d5e to your computer and use it in GitHub Desktop.

Select an option

Save sebglazebrook/9ac4aac479db58ac9d5e to your computer and use it in GitHub Desktop.
Call jruby from groovy/java
#test_ruby_class.rb
class TestRubyClass
attr_accessor :name, :birth_year
def initialize
@name = 'Yukihiro Matsumoto'
@birth_year = 1965
end
def age
Time.now.year - birth_year
end
end
TestRubyClass.new
---------------------------------- End of test_ruby_class.rb
//RubyWrapper.groovy
import org.jruby.embed.ScriptingContainer;
import org.jruby.javasupport.JavaEmbedUtils;
import org.jruby.runtime.builtin.IRubyObject;
class RubyWrapper {
def filename
def jruby
def rubyObject
RubyWrapper(filename){
this.filename = filename
loadRubyFile()
}
def propertyMissing(String name) {
rubyObject.callMethod(name)
}
def propertyMissing(String name, value) {
def args = new IRubyObject[1]
args[0] = JavaEmbedUtils.javaToRuby(rubyObject.getRuntime(), value)
rubyObject.callMethod("${name}=", args)
}
def methodMissing(String name, args) {
def rubyArgs = new IRubyObject[args.size()]
args.eachWithIndex{ arg, index ->
rubyArgs[index] = JavaEmbedUtils.javaToRuby(rubyObject.getRuntime(), arg)
}
rubyObject.callMethod(name,rubyArgs)
}
def private loadRubyFile(){
jruby = new ScriptingContainer()
def scriptStream = this.class.classLoader.getResourceAsStream("ruby/${filename}.rb")
rubyObject = jruby.runScriptlet(new InputStreamReader(scriptStream, "UTF-8"), new File("resources/ruby/${filename}.rb").getAbsolutePath())
}
}
--------------------------- End of RubyWrapper.groovy
// RubyWrapperTest.groovy
import spock.lang.Specification
class RubyWrapperTest extends Specification {
def "delegates property calls to the ruby object"(){
when:
def rubyWrapper = new RubyWrapper('test_ruby_class')
then:
rubyWrapper.name.asJavaString() == 'Yukihiro Matsumoto'
}
def "delegates property assignment to the ruby object"(){
given:
def rubyWrapper = new RubyWrapper('test_ruby_class')
when:
rubyWrapper.name = 'A new name'
then:
rubyWrapper.name.asJavaString() == 'A new name'
}
def "delegates method calls to the ruby object"(){
when:
def rubyWrapper = new RubyWrapper('test_ruby_class')
then:
rubyWrapper.age().to_s().asJavaString() == '49'
}
// @TODO this currently doesn't work. Need to convert a groovy closure to a ruby block
// def "evaluates closures included in the method invocation"(){
// }
}
--------------------------- End of RubyWrapperTest.groovy
// TODO
// Tweak to call static/class methods
// Add ability to send closures/blocks to methods
// Add error handling.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment