diff options
Diffstat (limited to 'actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/route_set.rb')
-rw-r--r-- | actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/route_set.rb | 409 |
1 files changed, 0 insertions, 409 deletions
diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/route_set.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/route_set.rb deleted file mode 100644 index 0e5a65a640..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/route_set.rb +++ /dev/null @@ -1,409 +0,0 @@ -require 'rack/mount/multimap' -require 'rack/mount/route' -require 'rack/mount/utils' - -module Rack::Mount - class RoutingError < StandardError; end - - class RouteSet - # Initialize a new RouteSet without optimizations - def self.new_without_optimizations(options = {}, &block) - new(options.merge(:_optimize => false), &block) - end - - # Basic RouteSet initializer. - # - # If a block is given, the set is yielded and finalized. - # - # See other aspects for other valid options: - # - <tt>Generation::RouteSet.new</tt> - # - <tt>Recognition::RouteSet.new</tt> - def initialize(options = {}, &block) - @parameters_key = options.delete(:parameters_key) || 'rack.routing_args' - @parameters_key.freeze - - @named_routes = {} - - @recognition_key_analyzer = Analysis::Splitting.new - @generation_key_analyzer = Analysis::Frequency.new - - @request_class = options.delete(:request_class) || Rack::Request - @valid_conditions = @request_class.public_instance_methods.map! { |m| m.to_sym } - - extend CodeGeneration unless options[:_optimize] == false - @optimized_recognize_defined = false - - @routes = [] - expire! - - if block_given? - yield self - rehash - end - end - - # Builder method to add a route to the set - # - # <tt>app</tt>:: A valid Rack app to call if the conditions are met. - # <tt>conditions</tt>:: A hash of conditions to match against. - # Conditions may be expressed as strings or - # regexps to match against. - # <tt>defaults</tt>:: A hash of values that always gets merged in - # <tt>name</tt>:: Symbol identifier for the route used with named - # route generations - def add_route(app, conditions = {}, defaults = {}, name = nil) - unless conditions.is_a?(Hash) - raise ArgumentError, 'conditions must be a Hash' - end - - unless conditions.all? { |method, pattern| - @valid_conditions.include?(method) - } - raise ArgumentError, 'conditions may only include ' + - @valid_conditions.inspect - end - - route = Route.new(app, conditions, defaults, name) - @routes << route - - @recognition_key_analyzer << route.conditions - - @named_routes[route.name] = route if route.name - @generation_key_analyzer << route.generation_keys - - expire! - route - end - - def recognize(obj) - raise 'route set not finalized' unless @recognition_graph - - cache = {} - keys = @recognition_keys.map { |key| - if key.respond_to?(:call) - key.call(cache, obj) - else - obj.send(key) - end - } - - @recognition_graph[*keys].each do |route| - matches = {} - params = route.defaults.dup - - if route.conditions.all? { |method, condition| - value = obj.send(method) - if condition.is_a?(Regexp) && (m = value.match(condition)) - matches[method] = m - captures = m.captures - route.named_captures[method].each do |k, i| - if v = captures[i] - params[k] = v - end - end - true - elsif value == condition - true - else - false - end - } - if block_given? - yield route, matches, params - else - return route, matches, params - end - end - end - - nil - end - - X_CASCADE = 'X-Cascade'.freeze - PASS = 'pass'.freeze - PATH_INFO = 'PATH_INFO'.freeze - - # Rack compatible recognition and dispatching method. Routes are - # tried until one returns a non-catch status code. If no routes - # match, the catch status code is returned. - # - # This method can only be invoked after the RouteSet has been - # finalized. - def call(env) - raise 'route set not finalized' unless @recognition_graph - - env[PATH_INFO] = Utils.normalize_path(env[PATH_INFO]) - - request = nil - req = @request_class.new(env) - recognize(req) do |route, matches, params| - # TODO: We only want to unescape params from uri related methods - params.each { |k, v| params[k] = Utils.unescape_uri(v) if v.is_a?(String) } - - if route.prefix? - env[Prefix::KEY] = matches[:path_info].to_s - end - - env[@parameters_key] = params - result = route.app.call(env) - return result unless result[1][X_CASCADE] == PASS - end - - request || [404, {'Content-Type' => 'text/html', 'X-Cascade' => 'pass'}, ['Not Found']] - end - - # Generates a url from Rack env and identifiers or significant keys. - # - # To generate a url by named route, pass the name in as a +Symbol+. - # url(env, :dashboard) # => "/dashboard" - # - # Additional parameters can be passed in as a hash - # url(env, :people, :id => "1") # => "/people/1" - # - # If no name route is given, it will fall back to a slower - # generation search. - # url(env, :controller => "people", :action => "show", :id => "1") - # # => "/people/1" - def url(env, *args) - named_route, params = nil, {} - - case args.length - when 2 - named_route, params = args[0], args[1].dup - when 1 - if args[0].is_a?(Hash) - params = args[0].dup - else - named_route = args[0] - end - else - raise ArgumentError - end - - only_path = params.delete(:only_path) - recall = env[@parameters_key] || {} - - unless result = generate(:all, named_route, params, recall, - :parameterize => lambda { |name, param| Utils.escape_uri(param) }) - return - end - - parts, params = result - return unless parts - - params.each do |k, v| - if v - params[k] = v - else - params.delete(k) - end - end - - req = stubbed_request_class.new(env) - req._stubbed_values = parts.merge(:query_string => Utils.build_nested_query(params)) - only_path ? req.fullpath : req.url - end - - def generate(method, *args) #:nodoc: - raise 'route set not finalized' unless @generation_graph - - method = nil if method == :all - named_route, params, recall, options = extract_params!(*args) - merged = recall.merge(params) - route = nil - - if named_route - if route = @named_routes[named_route.to_sym] - recall = route.defaults.merge(recall) - url = route.generate(method, params, recall, options) - [url, params] - else - raise RoutingError, "#{named_route} failed to generate from #{params.inspect}" - end - else - keys = @generation_keys.map { |key| - if k = merged[key] - k.to_s - else - nil - end - } - @generation_graph[*keys].each do |r| - next unless r.significant_params? - if url = r.generate(method, params, recall, options) - return [url, params] - end - end - - raise RoutingError, "No route matches #{params.inspect}" - end - end - - # Number of routes in the set - def length - @routes.length - end - - def rehash #:nodoc: - @recognition_keys = build_recognition_keys - @recognition_graph = build_recognition_graph - @generation_keys = build_generation_keys - @generation_graph = build_generation_graph - end - - # Finalizes the set and builds optimized data structures. You *must* - # freeze the set before you can use <tt>call</tt> and <tt>url</tt>. - # So remember to call freeze after you are done adding routes. - def freeze - unless frozen? - rehash - - @recognition_key_analyzer = nil - @generation_key_analyzer = nil - @valid_conditions = nil - - @routes.each { |route| route.freeze } - @routes.freeze - end - - super - end - - def marshal_dump #:nodoc: - hash = {} - - instance_variables_to_serialize.each do |ivar| - hash[ivar] = instance_variable_get(ivar) - end - - if graph = hash[:@recognition_graph] - hash[:@recognition_graph] = graph.dup - end - - hash - end - - def marshal_load(hash) #:nodoc: - hash.each do |ivar, value| - instance_variable_set(ivar, value) - end - end - - protected - def recognition_stats - { :keys => @recognition_keys, - :keys_size => @recognition_keys.size, - :graph_size => @recognition_graph.size, - :graph_height => @recognition_graph.height, - :graph_average_height => @recognition_graph.average_height } - end - - private - def expire! #:nodoc: - @recognition_keys = @recognition_graph = nil - @recognition_key_analyzer.expire! - - @generation_keys = @generation_graph = nil - @generation_key_analyzer.expire! - end - - def instance_variables_to_serialize - instance_variables.map { |ivar| ivar.to_sym } - [:@stubbed_request_class, :@optimized_recognize_defined] - end - - # An internal helper method for constructing a nested set from - # the linear route set. - # - # build_nested_route_set([:request_method, :path_info]) { |route, method| - # route.send(method) - # } - def build_nested_route_set(keys, &block) - graph = Multimap.new - @routes.each_with_index do |route, index| - catch(:skip) do - k = keys.map { |key| block.call(key, index) } - Utils.pop_trailing_nils!(k) - k.map! { |key| key || /.+/ } - graph[*k] = route - end - end - graph - end - - def build_recognition_graph - build_nested_route_set(@recognition_keys) { |k, i| - @recognition_key_analyzer.possible_keys[i][k] - } - end - - def build_recognition_keys - @recognition_key_analyzer.report - end - - def build_generation_graph - build_nested_route_set(@generation_keys) { |k, i| - throw :skip unless @routes[i].significant_params? - - if k = @generation_key_analyzer.possible_keys[i][k] - k.to_s - else - nil - end - } - end - - def build_generation_keys - @generation_key_analyzer.report - end - - def extract_params!(*args) - case args.length - when 4 - named_route, params, recall, options = args - when 3 - if args[0].is_a?(Hash) - params, recall, options = args - else - named_route, params, recall = args - end - when 2 - if args[0].is_a?(Hash) - params, recall = args - else - named_route, params = args - end - when 1 - if args[0].is_a?(Hash) - params = args[0] - else - named_route = args[0] - end - else - raise ArgumentError - end - - named_route ||= nil - params ||= {} - recall ||= {} - options ||= {} - - [named_route, params.dup, recall.dup, options.dup] - end - - def stubbed_request_class - @stubbed_request_class ||= begin - klass = Class.new(@request_class) - klass.public_instance_methods.each do |method| - next if method =~ /^__|object_id/ - klass.class_eval <<-RUBY - def #{method}(*args, &block) - @_stubbed_values[:#{method}] || super - end - RUBY - end - klass.class_eval { attr_accessor :_stubbed_values } - klass - end - end - end -end |