Class: Innate::Route

Inherits:
Object
  • Object
show all
Defined in:
lib/innate/route.rb

Overview

Innate support simple routing using string, regex and lambda based routers. Route are stored in a dictionary, which supports hash-like access but preserves order, so routes are evaluated in the order they are added.

This middleware should wrap Innate::DynaMap.

String routers are the simplest way to route in Innate. One path is translated into another:

Innate::Route[ '/foo' ] = '/bar'
  '/foo'  =>  '/bar'

Regex routers allow matching against paths using regex. Matches within your regex using () are substituted in the new path using printf-like syntax.

Innate::Route[ %r!^/(\d+)\.te?xt$! ] = "/text/%d"
  '/123.txt'  =>  '/text/123'
  '/789.text' =>  '/text/789'

For more complex routing, lambda routers can be used. Lambda routers are passed in the current path and request object, and must return either a new path string, or nil.

Innate::Route[ 'name of route' ] = lambda{ |path, request|
  '/bar' if path == '/foo' and request[:bar] == '1'
}
  '/foo'        =>  '/foo'
  '/foo?bar=1'  =>  '/bar'

Lambda routers can also use this alternative syntax:

Innate::Route('name of route') do |path, request|
  '/bar' if path == '/foo' and request[:bar] == '1'
end

NOTE: Use self::ROUTES notation in singleton methods to force correct

lookup.

Direct Known Subclasses

Rewrite

Constant Summary collapse

ROUTES =
[]

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app = Innate::DynaMap) ⇒ Route

Returns a new instance of Route.



58
59
60
# File 'lib/innate/route.rb', line 58

def initialize(app = Innate::DynaMap)
  @app = app
end

Class Method Details

.[](key) ⇒ Object



44
45
46
47
# File 'lib/innate/route.rb', line 44

def self.[](key)
  found = self::ROUTES.assoc(key)
  found[1] if found
end

.[]=(key, value) ⇒ Object



49
50
51
52
# File 'lib/innate/route.rb', line 49

def self.[]=(key, value)
  self::ROUTES.delete_if{|k,v| k == key }
  self::ROUTES << [key, value]
end

.clearObject



54
55
56
# File 'lib/innate/route.rb', line 54

def self.clear
  self::ROUTES.clear
end

Instance Method Details

#call(env) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
# File 'lib/innate/route.rb', line 62

def call(env)
  path = env['PATH_INFO']
  path << '/' if path.empty?

  if modified = resolve(path)
    Log.debug("%s routes %p to %p" % [self.class.name, path, modified])
    env['PATH_INFO'] = modified
  end

  @app.call(env)
end

#resolve(path) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/innate/route.rb', line 74

def resolve(path)
  self.class::ROUTES.each do |key, value|
    if key.is_a?(Regexp)
      md = path.match(key)
      return value % md.to_a[1..-1] if md

    elsif value.respond_to?(:call)
      new_path = value.call(path, Current.request)
      return new_path if new_path

    elsif value.respond_to?(:to_str)
      return value.to_str if path == key

    else
      Log.error("Invalid route %p => %p" % [key, value])
    end
  end

  nil
end