lib/roda.rb in roda-2.26.0 vs lib/roda.rb in roda-2.27.0

- old
+ new

@@ -685,15 +685,35 @@ matched end end + # Match the given class. Currently, the following classes + # are supported by default: + # Integer :: Match an integer segment, yielding result to block as an integer + # String :: Match any non-empty segment, yielding result to block as a string + def _match_class(klass) + meth = :"_match_class_#{klass}" + if respond_to?(meth, true) + send(meth) + else + unsupported_matcher(klass) + end + end + # Match the given hash if all hash matchers match. def _match_hash(hash) hash.all?{|k,v| send("match_#{k}", v)} end + # Match integer segment, and yield resulting value as an + # integer. + def _match_class_Integer + consume(/\A\/(\d+)(?=\/|\z)/){|i| [i.to_i]} + end + + # Match only if all of the arguments in the given array match. # Match the given regexp exactly if it matches a full segment. def _match_regexp(re) consume(self.class.cached_matcher(re){re}) end @@ -723,11 +743,11 @@ end end end # Match the given symbol if any segment matches. - def _match_symbol(sym) + def _match_symbol(sym=nil) rp = @remaining_path if rp[0, 1] == SLASH if last = rp.index('/', 1) if last > 1 @captures << rp[1, last-1] @@ -738,10 +758,13 @@ @remaining_path = EMPTY_STRING end end end + # Match any nonempty segment. This should be called without an argument. + alias _match_class_String _match_symbol + # The regular expression to use for matching symbols. By default, any non-empty # segment matches. def _match_symbol_regexp(s) SEGMENT end @@ -789,11 +812,13 @@ # SCRIPT_NAME to include the matched path, removes the matched # path from PATH_INFO, and updates captures with any regex captures. def consume(pattern) if matchdata = remaining_path.match(pattern) @remaining_path = matchdata.post_match - @captures.concat(matchdata.captures) + captures = matchdata.captures + captures = yield(*captures) if block_given? + @captures.concat(captures) end end # The default path to use for redirects when a path is not given. # For non-GET requests, redirects to the current path, which will @@ -834,21 +859,23 @@ else @remaining_path = path false end end - + # Attempt to match the argument to the given request, handling # common ruby types. def match(matcher) case matcher when String _match_string(matcher) - when Symbol - _match_symbol(matcher) + when Class + _match_class(matcher) when TERM empty_path? + when Symbol + _match_symbol(matcher) when Regexp _match_regexp(matcher) when Hash _match_hash(matcher) when Array @@ -856,14 +883,11 @@ when Proc matcher.call when true, false, nil matcher else - if roda_class.opts[:unsupported_matcher] == :raise - raise RodaError, "unsupported matcher: #{matcher.inspect}" - end - matcher + unsupported_matcher(matcher) end end # Match only if all of the arguments in the given array match. def match_all(args) @@ -882,9 +906,17 @@ # Whether string matchers are used verbatim, without handling # placeholders via colons. def placeholder_string_matcher? !roda_class.opts[:verbatim_string_matcher] + end + + # Handle an unsupported matcher. + def unsupported_matcher(matcher) + if roda_class.opts[:unsupported_matcher] == :raise + raise RodaError, "unsupported matcher: #{matcher.inspect}" + end + matcher end end # Class methods for RodaResponse module ResponseClassMethods