Porting a Ruby/Rails/MRI app to JRuby

2019-05-31 15:41发布

问题:

I have a Ruby/Rails devvelopment environment using rbenv, MRI Ruby (1.9.2-p290), rails 3.0.9, and SQLite3. I would like to port it to JRuby, but do it such that I don't have to do anything more than run "rbenv local jruby-1.6.4" and "rails server" in the root directory of the Rails application to use it with JRuby, and "rbenv local 1.9.2-p290" and "rails serer" to use it with MRI Ruby.

I am aware that the gems to access SQLite are different for Ruby versus JRuby, but how do you write the Gemfile such that the MRI-relevant gems are picked up when the Ruby is MRI, and the JRuby-relevant gems are picked up when the Ruby is JRuby?

I will also need to port it to MySQL instead of SQLite. Which gems do I need to use here for Ruby and JRuby?

For the record, I'm using Ubuntu 11.04, Ruby 1.9.2-p290, JRuby 1.6.4, and Rails 3.0.9 or 3.0.10.

回答1:

We ported a large Rails application to JRuby last year and it was a surprising amount of work. Granted, part of it had to do with the app being rather badly written and having lots of legacy code, but still. In case you wonder: most of our problems came from gems we used, which then sometimes depended on e.g. FFI that didn't properly work with JRuby at that time. A port to Rubinius I did a little later seemed a lot less painful, but was abandoned in favor of staying with MRI.

For the Gemfile, there's a platform option you can use. Here's an example from the Bundler docs:

gem "weakling",   :platforms => :jruby
gem "ruby-debug", :platforms => :mri_18
gem "nokogiri",   :platforms => [:mri_18, :jruby]

It also has a block form:

platforms :jruby do
  gem "foo"
end

Either form works well, since

All operations involving groups (bundle install, Bundler.setup, Bundler.require) behave exactly the same as if any groups not matching the current platform were explicitly excluded.

As a gem for MySQL I'd use the aptly named mysql, there seems to be a jdbc-mysql for JRuby.