Jay Godse
Jay Godse

Reputation: 15503

Ruby: Rails: MRI and JRuby

I have ported my Rails 3.0.10/MRI app on Ubuntu 11.04 to JRuby 1.6.4 on Ubuntu 11.04. My goal is to get to a place where I just have to do the following to run the app under JRuby.

railsapp1> rbenv local jruby-1.6.4
railsapp1> rails server

And to get the app working under MRI,

railsapp1> rbenv local 1.9.2-p290
railsapp1> rails server

The first part of this problem was to resolve the gems. To make this process work without code changes I did the following in the Rails Gemfile

platforms :mri do
    gem 'mysql2', '~>0.2.11'
end
platforms :jruby do
    gem 'jruby-openssl'
    gem 'activerecord-jdbcmysql-adapter'
end

Those gem statements were gotten using the brute-force method by creating dummy rails apps with different combinations of MRI/JRuby and SQLite/MySQL and then taking the gem statements from the generated Gemfiles for each combination.

That doesn't quite do it though. My config/database.yml file looks like this:

development:
    adapter: mysql2
    database: doodad
    username: doodad
    password: doodad
    host: localhost

This config/database.yml file only works for the MRI version. For the JRuby version, the config/database.yml file looks like this:

development:
    adapter: mysql
    database: doodad
    username: doodad
    password: doodad
    host: localhost

i.e. The only difference between the files is the name of the database adapter (mysql vs mysql2). Is there a way to tell the database.yml file or the system initializer to pick the adapter based on whether the Ruby environment is MRI or JRuby?

Upvotes: 2

Views: 1228

Answers (2)

Nick Sieger
Nick Sieger

Reputation: 3315

You can use ERB in your database.yml file:

development:
  adapter: <%= defined?(JRUBY_VERSION) ? "mysql" : "mysql2" %>
  ...

Upvotes: 7

tadman
tadman

Reputation: 211560

If all you need to do is twiddle your database.yml file, you have it pretty good. I generally avoid checking that in to the repository as different developers have different configurations, instead supplying only an example file.

Likewise when it comes to deployment, the server has a persistent configuration file that is shared between deploys. This allows you to fine-tune the settings without having to make changes to your repo just to accommodate an odd edge-case on one server.

If you're still bothered by this, you could make a wrapper around the JRuby mysql gem that registers it as mysql2 for the purposes of configuration, but that is probably a dangerous game to play as you're basically lying in your configuration, misleading people who might want to diagnose a problem they're having. People in this sense includes "future you" that has forgotten about this hack.

A safer alternative is to have two different but similar environments for development. You can call them whatever you want:

development_common: &development_common
  database: doodad
  username: doodad
  password: doodad
  host: localhost

development_jruby:
  <<: *development_common
  adapter: mysql

development_ruby:
  <<: *development_common
  adapter: mysql2

It's not that hard to set up your local environment to be one or the other as required, or to flip between the two by setting RAILS_ENV as required if doing integration tests in both worlds.

Upvotes: 0

Related Questions