Class: Otto::Route

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

Overview

Otto::Route

A Route is a definition of a URL path and the method to call when that path is requested. Each route represents a single line in a routes file.

e.g.

GET   /uri/path      YourApp.method
GET   /uri/path2     YourApp#method

Defined Under Namespace

Modules: ClassMethods

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(verb, path, definition) ⇒ Route

Returns a new instance of Route.



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/otto/route.rb', line 21

def initialize verb, path, definition
  @verb, @path, @definition = verb.to_s.upcase.to_sym, path, definition
  @pattern, @keys = *compile(@path)
  if !@definition.index('.').nil?
    @klass, @name = @definition.split('.')
    @kind = :class
  elsif !@definition.index('#').nil?
    @klass, @name = @definition.split('#')
    @kind = :instance
  else
    raise ArgumentError, "Bad definition: #{@definition}"
  end
  @klass = eval(@klass)
  #@method = eval(@klass).method(@name)
end

Instance Attribute Details

#definitionObject (readonly)

Returns the value of attribute definition.



19
20
21
# File 'lib/otto/route.rb', line 19

def definition
  @definition
end

#keysObject (readonly)

Returns the value of attribute keys.



19
20
21
# File 'lib/otto/route.rb', line 19

def keys
  @keys
end

#kindObject (readonly)

Returns the value of attribute kind.



19
20
21
# File 'lib/otto/route.rb', line 19

def kind
  @kind
end

#klassObject (readonly)

Returns the value of attribute klass.



19
20
21
# File 'lib/otto/route.rb', line 19

def klass
  @klass
end

#methodObject (readonly)

Returns the value of attribute method.



19
20
21
# File 'lib/otto/route.rb', line 19

def method
  @method
end

#nameObject (readonly)

Returns the value of attribute name.



19
20
21
# File 'lib/otto/route.rb', line 19

def name
  @name
end

#ottoObject

Returns the value of attribute otto.



20
21
22
# File 'lib/otto/route.rb', line 20

def otto
  @otto
end

#pathObject (readonly)

Returns the value of attribute path.



19
20
21
# File 'lib/otto/route.rb', line 19

def path
  @path
end

#patternObject (readonly)

Returns the value of attribute pattern.



19
20
21
# File 'lib/otto/route.rb', line 19

def pattern
  @pattern
end

#verbObject (readonly)

Returns the value of attribute verb.



19
20
21
# File 'lib/otto/route.rb', line 19

def verb
  @verb
end

Instance Method Details

#call(env, extra_params = {}) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/otto/route.rb', line 39

def call(env, extra_params={})
  extra_params ||= {}
  req = Rack::Request.new(env)
  res = Rack::Response.new
  req.extend Otto::RequestHelpers
  res.extend Otto::ResponseHelpers
  res.request = req
  req.params.merge! extra_params
  req.params.replace Otto::Static.indifferent_params(req.params)
  klass.extend Otto::Route::ClassMethods
  klass.otto = self.otto
  Otto.logger.debug "Route class: #{klass}"
  case kind
  when :instance
    inst = klass.new req, res
    inst.send(name)
  when :class
    klass.send(name, req, res)
  else
    raise RuntimeError, "Unsupported kind for #{@definition}: #{kind}"
  end
  res.body = [res.body] unless res.body.respond_to?(:each)
  res.finish
end

#compile(path) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/otto/route.rb', line 65

def compile(path)
  keys = []
  if path.respond_to? :to_str
    special_chars = %w{. + ( ) $}
    pattern =
      path.to_str.gsub(/((:\w+)|[\*#{special_chars.join}])/) do |match|
        case match
        when "*"
          keys << 'splat'
          "(.*?)"
        when *special_chars
          Regexp.escape(match)
        else
          keys << $2[1..-1]
          "([^/?#]+)"
        end
      end
    # Wrap the regex in parens so the regex works properly.
    # They can fail when there's an | for example (matching only the last one).
    # Note: this means we also need to remove the first matched value.
    [/\A(#{pattern})\z/, keys]
  elsif path.respond_to?(:keys) && path.respond_to?(:match)
    [path, path.keys]
  elsif path.respond_to?(:names) && path.respond_to?(:match)
    [path, path.names]
  elsif path.respond_to? :match
    [path, keys]
  else
    raise TypeError, path
  end
end

#pattern_regexpObject



36
37
38
# File 'lib/otto/route.rb', line 36

def pattern_regexp
  Regexp.new(@path.gsub(/\/\*/, '/.+'))
end