lib/innate/dynamap.rb in manveru-innate-2009.02.25 vs lib/innate/dynamap.rb in manveru-innate-2009.03.24

- old
+ new

@@ -1,40 +1,50 @@ module Innate + class URLMap < Rack::URLMap + def initialize(map = {}) + @originals = map + super + end - # This is a dynamic routing mapper used to outsmart Rack::URLMap - # Every time a mapping is changed a new Rack::URLMap will be put into - # Innate::DynaMap::CACHE[:map] - class DynaMap - MAP = {} - CACHE = {} + # super may raise when given invalid locations, so we only replace the + # `@originals` if we are sure the new map is valid + def remap(map) + value = super + @originals = map + value + end - # Delegate the call to the current Rack::URLMap instance. - # - # @note Currently Rack::URLMap will destructively modify PATH_INFO and - # SCRIPT_NAME, which leads to incorrect routing as parts of the PATH_INFO - # are cut out if they matched once. Here I repair this damage and hope - # that my patch to rack will be accepted. - # Update: patch was accepted, will remove it on next rack release - def self.call(env) - if app = CACHE[:map] - script_name, path_info = env['SCRIPT_NAME'], env['PATH_INFO'] - answer = app.call(env) - env.merge!('SCRIPT_NAME' => script_name, 'PATH_INFO' => path_info) - answer - else - raise "Nothing mapped yet" - end + def map(location, object) + return unless location and object + remap(@originals.merge(location.to_s => object)) end - # Map node to location, create a new Rack::URLMap instance and cache it. - def self.map(location, node) - return unless location - MAP[location.to_s] = node - CACHE[:map] = Rack::URLMap.new(MAP) + def at(location) + @originals[location] end + + def to(object) + @originals.invert[object] + end + + def to_hash + @originals.dup + end + + def call(env) + raise "Nothing mapped yet" if @originals.empty? + super + end end + DynaMap = URLMap.new + + # script_name, path_info = env['SCRIPT_NAME'], env['PATH_INFO'] + # answer = app.call(env) + # env.merge!('SCRIPT_NAME' => script_name, 'PATH_INFO' => path_info) + # answer + module SingletonMethods # Maps the given +object+ or +block+ to +location+, +object+ must respond to # #call in order to be of any use. # # @example with passed +object+ @@ -59,11 +69,11 @@ # map '/' # end # # Innate.at('/') # => Hello def at(location) - DynaMap::MAP[location.to_s] + DynaMap.at(location) end # Returns one of the paths the given +object+ is mapped to. # # @example @@ -73,9 +83,9 @@ # map '/' # end # # Innate.to(Hello) # => '/' def to(object) - DynaMap::MAP.invert[object] + DynaMap.to(object) end end end