Start a Rack app with multiple interpreters
Late last week I was looking at source of discourse and I stumbled upon their Gemfile
which is particularly interesting since it shows a way to have a different lockfile depending on a condition. They mainly use it to ensure compatibility between Rails 3 and Rails 4 but this gave me an idea. Since I'm often required to run Rails apps using different interpreters, mainly MRI and jRuby I thought it might be a good idea to use their code to fit my needs so I quickly added the following lines to my Gemfile
:
# monkey patching to support dual booting
module Bundler::SharedHelpers
def default_lockfile=(path)
@default_lockfile = path
end
def default_lockfile
@default_lockfile ||= Pathname.new("#{default_gemfile}.lock")
end
end
module ::Kernel
def jruby?
!(RUBY_PLATFORM =~ /java/).nil?
end
end
if jruby?
Bundler::SharedHelpers.default_lockfile = Pathname.new("#{Bundler::SharedHelpers.default_gemfile}_jruby.lock")
# Bundler::Dsl.evaluate already called with an incorrect lockfile ... fix it
class Bundler::Dsl
# A bit messy, this can be called multiple times by bundler, avoid blowing the stack
unless self.method_defined? :to_definition_unpatched
alias_method :to_definition_unpatched, :to_definition
end
def to_definition(bad_lockfile, unlock)
to_definition_unpatched(Bundler::SharedHelpers.default_lockfile, unlock)
end
end
end
It ables me to handle both MRI and jRuby at the same time and run my Rails apps either using one or the other at the same time. For example it means I can start them this way:
$ ruby -S bundle exec rails s -p 3000 -P tmp/pid/server.pid
$ jruby -S bundle exec rails s -p 3001 -P tmp/pid/server_jruby.pid
Then if you use it nginx you could set up an upstream which proxies your request to the different instances which is kinda cool IMO.