Will man zwei mit Sinatra gebaute Webanwendungen gleichzeitig ausführen stellt sich zuerst die Frage: Geht das überhaupt? Die Antwort: Vielleicht.
Man kann natürlich immer zwei Ruby-Prozesse starten und auf verschiedenen Ports horchen. Hier geht es aber darum, zwei Anwendungen auf dem gleichen Port so zu kombinieren, dass zum Beispiel die eine auf / reagiert, die andere ab /blog/ übernimmt.
Das geht nicht, wenn beide Anwendungen dem klassischen Stil folgen, denn davon darf es nur eine pro Ruby-Prozess geben. Stackoverflow behauptet zwar etwas anderes, aber der Antwort zufolge haben Fragesteller wie Beantworter nicht verstanden, was der klassische Stil ist, denn mit App.new
kann man eine darin gebaute Anwendung nicht starten (oder ich habe da eine Lücke). Also muss entweder die zweite oder beide Anwendungen im modularen Stil gebaut sein. Glücklicherweise ist das Umwandeln vom klassischen Stil in den modularen einfach, und nochmal einfacher wenn Sinatra::Application statt Sinatra::Base benutzt wird.
Bei mir liegt die erste, die klassische Sinatra-Anwendung, im Hauptverzeichnis. Die modulare liegt in einem Unterverzeichnis dann. Den beiden Anwendungen kann ihr Startpunkt dann in der config.ru mittels Rack::URLMap
zugewiesen werden:
require 'rubygems'
require 'bundler'
Bundler.require
require './static-server.rb'
require './modularapp/modular-server.rb'
run Rack::URLMap.new(
'/' => Sinatra::Application,
'/blog' => Moularapp::Modularapp.new # Modularapp also got a module to prevent collisions
)
Es fehlen noch die gems. Denn die sollen per Bundler installiert werden, doch Bundler.require
würde ja normalerweise nur die erste Gemfile auslesen. Deshalb verweist man an deren Ende auf die zweite:
Dir.glob(File.join(File.dirname(__FILE__), 'modularapp, "Gemfile")) do |gemfile|
eval(IO.read(gemfile), binding)
end
Bundler installiert nun alles nötig, URLMap weist den Anwendungen den richtigen Startpunkt zu, und ein <cpde>rackup führt beide auf einmal aus. Es geht also.