module Roda::RodaPlugins::OptimizedMatching::RequestMethods

  1. lib/roda/plugins/_optimized_matching.rb

Methods

Public Instance

  1. is
  2. on

Public Instance methods

is(*args, &block)

Optimize the r.is method handling of a single string, String, Integer, regexp, or true, argument.

[show source]
   # File lib/roda/plugins/_optimized_matching.rb
22 def is(*args, &block)
23   case args.length
24   when 1
25     _is1(args, &block)
26   when 0
27     always(&block) if @remaining_path.empty?
28   else
29     if_match(args << TERM, &block)
30   end
31 end
on(*args, &block)

Optimize the r.on method handling of a single string, String, Integer, or regexp argument. Inline the related matching code to avoid the need to modify @captures.

[show source]
    # File lib/roda/plugins/_optimized_matching.rb
 36 def on(*args, &block)
 37   case args.length
 38   when 1
 39     case matcher = args[0]
 40     when String
 41       always{yield} if _match_string(matcher)
 42     when Class
 43       if matcher == String
 44         rp = @remaining_path
 45         if rp.getbyte(0) == 47
 46           if last = rp.index('/', 1)
 47             return false if last == 1
 48             @remaining_path = rp[last, rp.length]
 49             always{yield rp[1, last-1]}
 50           elsif (len = rp.length) > 1
 51             @remaining_path = ""
 52             always{yield rp[1, len]}
 53           end
 54         end
 55       elsif matcher == Integer
 56         rp = @remaining_path
 57         if /\A\/(\d{1,100})(?=\/|\z)/.match?(rp)
 58           if last = rp.index('/', 1)
 59             value = rp[1, last-1]
 60             rp = rp[last, rp.length]
 61           else
 62             value = rp[1, rp.length]
 63             rp = ""
 64           end
 65 
 66           if value = scope.send(:_convert_class_Integer, value)
 67             @remaining_path = rp
 68             always{yield(value)}
 69           end
 70         end
 71       else
 72         path = @remaining_path
 73         captures = @captures.clear
 74         meth = :"_match_class_#{matcher}"
 75         if respond_to?(meth, true)
 76           # Allow calling private methods, as match methods are generally private
 77           if send(meth, &block)
 78             block_result(yield(*captures))
 79             throw :halt, response.finish
 80           else
 81             @remaining_path = path
 82             false
 83           end
 84         else
 85           unsupported_matcher(matcher)
 86         end
 87       end
 88     when Regexp
 89       if matchdata = self.class.cached_matcher(matcher){matcher}.match(@remaining_path)
 90         @remaining_path = matchdata.post_match
 91         always{yield(*matchdata.captures)}
 92       end
 93     when true
 94       always(&block)
 95     when false, nil
 96       # nothing
 97     else
 98       path = @remaining_path
 99       captures = @captures.clear
100 
101       matched = case matcher
102       when Array
103         _match_array(matcher)
104       when Hash
105         _match_hash(matcher)
106       when Symbol
107         _match_symbol(matcher)
108       when Proc
109         matcher.call
110       else
111         unsupported_matcher(matcher)
112       end
113 
114       if matched
115         block_result(yield(*captures))
116         throw :halt, response.finish
117       else
118         @remaining_path = path
119         false
120       end
121     end
122   when 0
123     always(&block)
124   else
125     if_match(args, &block)
126   end
127 end