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_keys = [:controller, :action] @generation_route_keys = [] @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 56 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_route_keys << 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, then 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 134 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 old_params = env[@parameters_key] env[@parameters_key] = (old_params || {}).merge(params) result = route.app.call(env) if result[1][X_CASCADE] == PASS env[@parameters_key] = old_params else return result end 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 269 def freeze unless frozen? rehash stubbed_request_class @recognition_key_analyzer = nil @generation_route_keys = 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 252 def length @routes.length end
# File lib/rack/mount/route_set.rb, line 80 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 named 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 176 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 286 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.