Class ActionController::Routing::RouteBuilder
In: vendor/rails/actionpack/lib/action_controller/routing.rb
Parent: Object

Methods

Attributes

optional_separators  [RW] 
separators  [RW] 

Public Class methods

[Source]

     # File vendor/rails/actionpack/lib/action_controller/routing.rb, line 787
787:       def initialize
788:         self.separators = Routing::SEPARATORS
789:         self.optional_separators = %w( / )
790:       end

Public Instance methods

Takes a hash of defaults and a hash of requirements, and assigns them to the segments. Any unused requirements (which do not correspond to a segment) are returned as a hash.

[Source]

     # File vendor/rails/actionpack/lib/action_controller/routing.rb, line 863
863:       def assign_route_options(segments, defaults, requirements)
864:         route_requirements = {} # Requirements that do not belong to a segment
865:     
866:         segment_named = Proc.new do |key|
867:           segments.detect { |segment| segment.key == key if segment.respond_to?(:key) }
868:         end
869:     
870:         requirements.each do |key, requirement|
871:           segment = segment_named[key]
872:           if segment
873:             raise TypeError, "#{key}: requirements on a path segment must be regular expressions" unless requirement.is_a?(Regexp)
874:             if requirement.source =~ %r{\A(\\A|\^^)|(\\Z|\\z|\$)\Z}
875:               raise ArgumentError, "Regexp anchor characters are not allowed in routing requirements: #{requirement.inspect}"
876:             end
877:             segment.regexp = requirement
878:           else
879:             route_requirements[key] = requirement
880:           end
881:         end
882:     
883:         defaults.each do |key, default|
884:           segment = segment_named[key]
885:           raise ArgumentError, "#{key}: No matching segment exists; cannot assign default" unless segment
886:           segment.is_optional = true
887:           segment.default = default.to_param if default
888:         end
889: 
890:         ensure_required_segments(segments)
891:         route_requirements
892:       end

Construct and return a route with the given path and options.

[Source]

     # File vendor/rails/actionpack/lib/action_controller/routing.rb, line 914
914:       def build(path, options)
915:         # Wrap the path with slashes
916:         path = "/#{path}" unless path[0] == ?/
917:         path = "#{path}/" unless path[-1] == ?/
918:     
919:         segments = segments_for_route_path(path)
920:         defaults, requirements, conditions = divide_route_options(segments, options)
921:         requirements = assign_route_options(segments, defaults, requirements)
922: 
923:         route = Route.new
924:         route.segments = segments
925:         route.requirements = requirements
926:         route.conditions = conditions
927: 
928:         if !route.significant_keys.include?(:action) && !route.requirements[:action]
929:           route.requirements[:action] = "index"
930:           route.significant_keys << :action
931:         end
932: 
933:         route
934:       end

Split the given hash of options into requirement and default hashes. The segments are passed alongside in order to distinguish between default values and requirements.

[Source]

     # File vendor/rails/actionpack/lib/action_controller/routing.rb, line 845
845:       def divide_route_options(segments, options)
846:         options = options.dup
847:         requirements = (options.delete(:requirements) || {}).dup
848:         defaults     = (options.delete(:defaults)     || {}).dup
849:         conditions   = (options.delete(:conditions)   || {}).dup
850: 
851:         path_keys = segments.collect { |segment| segment.key if segment.respond_to?(:key) }.compact
852:         options.each do |key, value|
853:           hash = (path_keys.include?(key) && ! value.is_a?(Regexp)) ? defaults : requirements
854:           hash[key] = value
855:         end
856:     
857:         [defaults, requirements, conditions]
858:       end

Makes sure that there are no optional segments that precede a required segment. If any are found that precede a required segment, they are made required.

[Source]

     # File vendor/rails/actionpack/lib/action_controller/routing.rb, line 897
897:       def ensure_required_segments(segments)
898:         allow_optional = true
899:         segments.reverse_each do |segment|
900:           allow_optional &&= segment.optional?
901:           if !allow_optional && segment.optional?
902:             unless segment.optionality_implied?
903:               warn "Route segment \"#{segment.to_s}\" cannot be optional because it precedes a required segment. This segment will be required."
904:             end
905:             segment.is_optional = false
906:           elsif allow_optional & segment.respond_to?(:default) && segment.default
907:             # if a segment has a default, then it is optional
908:             segment.is_optional = true
909:           end
910:         end
911:       end

[Source]

     # File vendor/rails/actionpack/lib/action_controller/routing.rb, line 796
796:       def interval_regexp
797:         Regexp.new "(.*?)(#{separators.source}|$)"
798:       end

A factory method that returns a new segment instance appropriate for the format of the given string.

[Source]

     # File vendor/rails/actionpack/lib/action_controller/routing.rb, line 818
818:       def segment_for(string)
819:         segment = case string
820:           when /\A:(\w+)/
821:             key = $1.to_sym
822:             case key
823:               when :action then DynamicSegment.new(key, :default => 'index')
824:               when :id then DynamicSegment.new(key, :optional => true)
825:               when :controller then ControllerSegment.new(key)
826:               else DynamicSegment.new key
827:             end
828:           when /\A\*(\w+)/ then PathSegment.new($1.to_sym, :optional => true)
829:           when /\A\?(.*?)\?/
830:             returning segment = StaticSegment.new($1) do
831:               segment.is_optional = true
832:             end
833:           when /\A(#{separator_pattern(:inverted)}+)/ then StaticSegment.new($1)
834:           when Regexp.new(separator_pattern) then
835:             returning segment = DividerSegment.new($&) do
836:               segment.is_optional = (optional_separators.include? $&)
837:             end
838:         end
839:         [segment, $~.post_match]
840:       end

Accepts a "route path" (a string defining a route), and returns the array of segments that corresponds to it. Note that the segment array is only partially initialized—the defaults and requirements, for instance, need to be set separately, via the assign_route_options method, and the optional? method for each segment will not be reliable until after assign_route_options is called, as well.

[Source]

     # File vendor/rails/actionpack/lib/action_controller/routing.rb, line 806
806:       def segments_for_route_path(path)
807:         rest, segments = path, []
808:     
809:         until rest.empty?
810:           segment, rest = segment_for rest
811:           segments << segment
812:         end
813:         segments
814:       end

[Source]

     # File vendor/rails/actionpack/lib/action_controller/routing.rb, line 792
792:       def separator_pattern(inverted = false)
793:         "[#{'^' if inverted}#{Regexp.escape(separators.join)}]"
794:       end

[Validate]