Rails源代码分析(35):ActionController::Routing(6) Segment

来源:互联网 发布:如何绕开公司网络限制 编辑:程序博客网 时间:2024/04/28 13:40
1 Segment的分类
  • Segment.   Abstract Base Class
  • DynamicSegment. This represents parts of the route that begin with a colon, like :action:permalink or :id.
  • ControllerSegment. This is actually a subclass ofDynamicSegment. It represents to special string :controller, because it does some special recognition on those strings. (We’ll cover that more in the next article).
  • PathSegment. This is for segments that start with an asterisk, and which represent the remainder of the path. Routes like "/file/*path" use a PathSegment.
  • StaticSegment. This is any static text in your route that must be matched (or generated) verbatim. If you have a path like "/one/two", the strings "one" and "two" are both static segments.
  • DividerSegment. This is any segment that is used to delimit the other segments. Generally, this will be the forward slash character, but also includes commas, periods, semicolons, and question marks.
2 实现
  先看看Segment实现
  1.     class Segment #:nodoc:
  2.       RESERVED_PCHAR = ':@&=+$,;'
  3.       UNSAFE_PCHAR = Regexp.new("[^#{URI::REGEXP::PATTERN::UNRESERVED}#{RESERVED_PCHAR}]"false'N').freeze
  4.       attr_accessor :is_optional
  5.       alias_method :optional?, :is_optional
  6.       def initialize
  7.         self.is_optional = false
  8.       end
  9.       def extraction_code
  10.         nil
  11.       end
  12.       # Continue generating string for the prior segments.
  13.       def continue_string_structure(prior_segments)
  14.         if prior_segments.empty?
  15.           interpolation_statement(prior_segments)
  16.         else
  17.           new_priors = prior_segments[0..-2]
  18.           prior_segments.last.string_structure(new_priors)
  19.         end
  20.       end
  21.       def interpolation_chunk
  22.         URI.escape(value, UNSAFE_PCHAR)
  23.       end
  24.       # Return a string interpolation statement for this segment and those before it.
  25.       def interpolation_statement(prior_segments)
  26.         chunks = prior_segments.collect { |s| s.interpolation_chunk }
  27.         chunks << interpolation_chunk
  28.         "/"#{chunks * ''}/"#{all_optionals_available_condition(prior_segments)}"
  29.       end
  30.       def string_structure(prior_segments)
  31.         optional? ? continue_string_structure(prior_segments) : interpolation_statement(prior_segments)
  32.       end
  33.       # Return an if condition that is true if all the prior segments can be generated.
  34.       # If there are no optional segments before this one, then nil is returned.
  35.       def all_optionals_available_condition(prior_segments)
  36.         optional_locals = prior_segments.collect { |s| s.local_name if s.optional? && s.respond_to?(:local_name) }.compact
  37.         optional_locals.empty? ? nil : " if #{optional_locals * ' && '}"
  38.       end
  39.       # Recognition
  40.       def match_extraction(next_capture)
  41.         nil
  42.       end
  43.       # Warning
  44.       # Returns true if this segment is optional? because of a default. If so, then
  45.       # no warning will be emitted regarding this segment.
  46.       def optionality_implied?
  47.         false
  48.       end
  49.     end