class HttpRouter::Node::Root

Attributes

compiled[R]
compiled?[R]
methods_module[R]

Public Class Methods

new(router) click to toggle source
Calls superclass method HttpRouter::Node.new
# File lib/http_router/node/root.rb, line 6
def initialize(router)
  super(router, nil)
  @counter, @methods_module = 0, Module.new
end

Public Instance Methods

compile(routes) click to toggle source
# File lib/http_router/node/root.rb, line 33
def compile(routes)
  routes.each {|route| add_route(route)}
  root.extend(root.methods_module)
  instance_eval "def call(request, &callback)\n#{to_code}\nnil\nend"
  @compiled = true
end
depth() click to toggle source
# File lib/http_router/node/root.rb, line 25
def depth
  0
end
inject_root_ivar(obj) click to toggle source
# File lib/http_router/node/root.rb, line 19
def inject_root_ivar(obj)
  name = :"@ivar_#{@counter += 1}"
  root.instance_variable_set(name, obj)
  name
end
inspect_label() click to toggle source
# File lib/http_router/node/root.rb, line 29
def inspect_label
  "Root (#{@matchers.size} matchers)"
end
next_counter() click to toggle source
# File lib/http_router/node/root.rb, line 15
def next_counter
  @counter += 1
end
uncompile() click to toggle source
# File lib/http_router/node/root.rb, line 11
def uncompile
  instance_eval "undef :call; def call(req); raise 'uncompiled root'; end", __FILE__, __LINE__ if compiled?
end

Private Instance Methods

add_complex_part(route, node, parts, path_generator) click to toggle source
# File lib/http_router/node/root.rb, line 106
def add_complex_part(route, node, parts, path_generator)
  capturing_indicies, splitting_indicies, captures, spans = [], [], 0, false
  regex = parts.inject('') do |reg, part|
    reg << case part[0]
    when ?\\ then Regexp.quote(part[1].chr)
    when ?:, ?*
      spans = true if part[0] == ?*
      captures += 1
      (part[0] == ?* ? splitting_indicies : capturing_indicies) << captures
      name = part[1, part.size].to_sym
      path_generator.param_names << name.to_sym
      if spans
        route.matches_with(name) ? "((?:#{route.matches_with(name)}\\/?)+)" : '(.*?)'
      else
        "(#{(route.matches_with(name) || '[^/]*?')})"
      end
    else
      Regexp.quote(part)
    end
  end
  spans ? node.add_spanning_match(Regexp.new("#{regex}$"), capturing_indicies, splitting_indicies) :
    node.add_match(Regexp.new("#{regex}$"), capturing_indicies, splitting_indicies)
end
add_non_path_to_tree(route, node, path, param_names) click to toggle source
# File lib/http_router/node/root.rb, line 130
def add_non_path_to_tree(route, node, path, param_names)
  node = node.add_host([route.host, route.other_hosts].flatten.compact) if route.host or route.other_hosts
  node = node.add_user_agent(route.user_agent) if route.user_agent
  node = node.add_scheme(route.scheme) if route.scheme
  node = node.add_request_method(route.request_methods) if route.request_methods
  path_obj = node.add_destination(route, path, param_names)
  path_obj
end
add_normal_part(route, node, part, path_generator) click to toggle source
# File lib/http_router/node/root.rb, line 90
def add_normal_part(route, node, part, path_generator)
  name = part[1, part.size]
  node = case part[0]
  when ?\           node.add_lookup(part[1].chr)
  when ?:
    path_generator.param_names << name.to_sym
    route.matches_with(name) ? node.add_spanning_match(route.matches_with(name)) : node.add_variable
  when ?*
    path_generator.param_names << name.to_sym
    route.matches_with(name) ? node.add_glob_regexp(route.matches_with(name)) : node.add_glob
  else
    node.add_lookup(part)
  end
end
add_route(route) click to toggle source
# File lib/http_router/node/root.rb, line 41
def add_route(route)
  paths = if route.path_for_generation.nil?
    route.match_partially = true
    []
  elsif route.path_for_generation.is_a?(Regexp)
    [route.path_for_generation]
  else
    path_for_generation = route.path_for_generation.dup
    start_index, end_index = 0, 1
    raw_paths, chars = [""], path_for_generation.split('')
    until chars.empty?
      case chars.first[0]
      when ?(
        chars.shift
        (start_index...end_index).each { |path_index| raw_paths << raw_paths[path_index].dup }
        start_index = end_index
        end_index = raw_paths.size
      when ?)
        chars.shift
        start_index -= end_index - start_index
      else
        c = if chars[0][0] == ?\\ && (chars[1][0] == ?( || chars[1][0] == ?)); chars.shift; chars.shift; else; chars.shift; end
        (start_index...end_index).each { |path_index| raw_paths[path_index] << c } 
      end
    end
    raw_paths
  end
  paths.reverse!
  if paths.empty?
    add_non_path_to_tree(route, @router.root, nil, [])
  else
    Generator.new(route, paths).each_path do |path_generator|
      case path_generator.path
      when Regexp
        path_generator.param_names = path_generator.path.names.map(&:to_sym) if path_generator.path.respond_to?(:names)
        add_non_path_to_tree(route, add_free_match(path_generator.path), path_generator.path, path_generator.param_names)
      else
        node = self
        path_generator.path.split(/\//).each do |part|
          next if part == ''
          parts = part.scan(/\.|[:*][a-z0-9_]+|[^:*\]+/)
          node = parts.size == 1 ? add_normal_part(route, node, part, path_generator) : add_complex_part(route, node, parts, path_generator)
        end
        add_non_path_to_tree(route, node, path_generator.path, path_generator.param_names)
      end
    end
  end
end