2016-07-08 24 views
0

Ich habe eine .ru-Datei und kann Mappings ohne Problem einrichten (die 'Register' Mapping unten). in anderen ZuordnungenRuby rackup: Ist es möglich, ein Mapping innerhalb eines anderen Mappings programmatisch hinzuzufügen?

Allerdings möchte ich Dienste selbst registrieren können, indem Sie eine URL schlagen, damit ich on the fly von neuen Zuordnungen können, hinzufügen möchten. obwohl

Der Code unten funktioniert nicht Arbeit. Was mache ich falsch und ist das möglich?

Danke!

map '/register' do 
    run Proc.new { |env| 
    # inside of register i want to add another mapping. 
    # obviously 'bar' would be a value read out of env 
    map '/bar' do 
     run Proc.new{ |env| ['200', { 'Content-Type' => 'text/html' },'bar' } 
    end 

    [ '200', {'Content-Type' => 'text/html'}, "registered"] 
    } 
end 

Antwort

1

Ich glaube nicht, gibt es eine Möglichkeit Routen After-the-fact hinzufügen map verwenden. Eine Alternative ist die Verwendung von Rack::URLMap, um Ihre App zu definieren. Sie müssen Ihre eigene Liste der registrierten Routen (als Hash) und Rack::URLMap#remap Sie den Hash eine neue Route hinzufügen jedes Mal rufen halten:

url_map = Rack::URLMap.new 
routes = { 
    "/register" => lambda do |env| 
    routes["/bar"] = lambda do |env| 
     [ "200", {"Content-Type" => "text/plain"}, ["bar"] ] 
    end 

    url_map.remap(routes) 

    [ "200", {"Content-Type" => "text/plain"}, ["registered"] ] 
    end 
} 

url_map.remap(routes) 
run url_map 

Beachten Sie, dass Sie mit nur mit dem Hash tun könnten, aber URLMap bietet einige nette Annehmlichkeiten, einschließlich 404-Behandlung. Es ist wirklich eine wirklich nette kleine Klasse und worth reading, wenn Sie fünf Minuten übrig haben.

Wenn Sie so geneigt waren, könnten Sie diese in eine ordentlich wenig Klasse drehen:

class Application 
    def initialize 
    @routes = {} 
    @url_map = Rack::URLMap.new 

    register_route "/register" do |env| 
     # When "/register" is requested, register the new route "/bar" 
     register_route "/bar" do |env| 
     [ 200, {"Content-Type" => "text/plain"}, ["bar"] ] 
     end 
     [ 200, {"Content-Type" => "text/plain"}, ["registered"] ] 
    end 
    end 

    def call(env) 
    @url_map.call(env) 
    end 

    private 
    def register_route(path, &block) 
    @routes[path] = block 
    @url_map.remap(@routes) 
    end 
end 

run Application.new 
+0

das funktioniert. Danke!!! – Poul

0

Nach https://rack.github.io/ „Rack zu benutzen, stellt eine‚app‘: ein Objekt, das auf das Anrufverfahren reagiert, die Umwelt Hash als Parameter nehmen, und Zurückkehren ein Array mit drei Elementen:

  • der HTTP-Antwortcode
  • Ein Hash von Headern
  • Die Antwort Körper, der auf each "
reagieren muss

Ihr drittes Element reagiert nicht auf each. Vielleicht wickle es in ein Array?

+0

Sie richtig sind, dass „registriert“ und „bar“ in einem Array sein müssen, aber das hat immer noch nicht 'bar' registriert – Poul