jruby-scala-collections is a tiny interoperability library for passing JRuby/Scala collections back and forth.
https://rubygems.org/gems/jruby-scala-collections
$ gem install jruby-scala-collections
With bundler:
gem "jruby-scala-collections", ">=0.1.1", require: "jruby/scala_support"
Beware that you have to have scala-library.jar
loaded before you
load jruby/scala_support
. In Rails this generally means it loading in config/boot.rb
.
Each Object
has two methods: #to_scala
and #from_scala
.
These can be used to wrap JRuby/Scala collections.
Example:
gem 'jruby-scala-collections'
require 'jruby/scala_support'
r_arr = [1,2,3,4]
scala_arr = scala_object.do_stuff(r_arr.to_scala)
scala_arr.from_scala
Array#to_scala
becomesscala.collection.mutable.Buffer
Hash#to_scala
becomesscala.collection.mutable.Map
Set#to_scala
becomesscala.collection.mutable.Set
Take note that even collections inside collections are wrapped:
> a = [1,[2,3],{4=>5}].to_scala
=> #<Java::JrubyCollection::ListWrapper:0x768bdb>
> a.apply(1)
=> #<Java::JrubyCollection::ListWrapper:0x884ab9>
> a.apply(2)
=> #<Java::JrubyCollection::MapWrapper:0x1bb605>
From Scala side Ruby primitives are converted using default JRuby conversions that are listed in https://github.com/jruby/jruby/wiki/CallingJavaFromJRuby section "Conversion of Types".
So if you expect Array of Fixnums coming to your scala method, it should accept:
// Either
def scalaMethod(args: collection.mutable.Buffer[Long])
// Or
def scalaMethod(args: collection.Seq[Long])
It also adds #Some
and None
so you could pass values to Scala
methods:
scala_object.set(Some(3))
scala_object.get(None)
This library was written by Artūras 'arturaz' Šlajus for personal usage.
#to_scala
should work pretty well, however Ruby wrappers
in #from_scala
may be missing methods. Patches are welcome.
jruby-scala-collections uses rubyspec and mspec to test that the behaviour
of the Ruby wrappers is correct.
Currently only a part of those tests pass. You can contribute by grabbing
any of the tests marked as fails
in rubyspec/tags/**/*_tags.txt
, marking it as
focus
and implement the needed behaviour.
Guard is configured so that bundle exec guard
runs all tests that have the focus tag.
If you want to run all tests that should be working, use bundle exec mspec -G fails rubyspec
.
If you have implemented functionality, run bundle exec mspec tag rubyspec
to update the list
of failing tests and check with a git diff
that you haven't broken other functionality.
In order to compile and package the project, an existing SBT installation must be available. Then just go to the
ext
directory and execute sbt dist
. Then go back to the upper directory and execute gem build jruby-scala-collections.gemspec