Object
Basic RouteSet initializer.
If a block is given, the set is yielded and finalized.
See other aspects for other valid options:
Generation::RouteSet.new
Recognition::RouteSet.new
# File lib/rack/mount/route_set.rb, line 21 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
Initialize a new RouteSet without optimizations
# File lib/rack/mount/route_set.rb, line 10 def self.new_without_optimizations(options = {}, &block) new(options.merge(:_optimize => false), &block) end
Builder method to add a route to the set
app |
A valid Rack app to call if the conditions are met. |
conditions |
A hash of conditions to match against. Conditions may be expressed as strings or regexps to match against. |
defaults |
A hash of values that always gets merged in |
name |
Symbol identifier for the route used with named route generations |
# File lib/rack/mount/route_set.rb, line 54 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
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.
# File lib/rack/mount/route_set.rb, line 132 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
Finalizes the set and builds optimized data structures. You must freeze the set before you can use call and url. So remember to call freeze after you are done adding routes.
# File lib/rack/mount/route_set.rb, line 261 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
Number of routes in the set
# File lib/rack/mount/route_set.rb, line 243 def length @routes.length end
# File lib/rack/mount/route_set.rb, line 78 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
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"
# File lib/rack/mount/route_set.rb, line 167 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
# File lib/rack/mount/route_set.rb, line 297 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
Generated with the Darkfish Rdoc Generator 2.