Class: ActionController::Routing::RouteBuilder
- Defined in:
- lib/action_controller/routing.rb
Overview
:nodoc:
Instance Attribute Summary collapse
-
#optional_separators ⇒ Object
Returns the value of attribute optional_separators.
-
#separators ⇒ Object
Returns the value of attribute separators.
Instance Method Summary collapse
-
#assign_default_route_options(segments) ⇒ Object
Assign default options, such as ‘index’ as a default for :action.
-
#assign_route_options(segments, defaults, requirements) ⇒ Object
Takes a hash of defaults and a hash of requirements, and assigns them to the segments.
-
#build(path, options) ⇒ Object
Construct and return a route with the given path and options.
-
#divide_route_options(segments, options) ⇒ Object
Split the given hash of options into requirement and default hashes.
-
#ensure_required_segments(segments) ⇒ Object
Makes sure that there are no optional segments that precede a required segment.
-
#initialize ⇒ RouteBuilder
constructor
A new instance of RouteBuilder.
- #interval_regexp ⇒ Object
-
#segment_for(string) ⇒ Object
A factory method that returns a new segment instance appropriate for the format of the given string.
-
#segments_for_route_path(path) ⇒ Object
Accepts a “route path” (a string defining a route), and returns the array of segments that corresponds to it.
- #separator_pattern(inverted = false) ⇒ Object
Constructor Details
#initialize ⇒ RouteBuilder
Returns a new instance of RouteBuilder.
790 791 792 793 |
# File 'lib/action_controller/routing.rb', line 790 def initialize self.separators = Routing::SEPARATORS self.optional_separators = %w( / ) end |
Instance Attribute Details
#optional_separators ⇒ Object
Returns the value of attribute optional_separators.
788 789 790 |
# File 'lib/action_controller/routing.rb', line 788 def optional_separators @optional_separators end |
#separators ⇒ Object
Returns the value of attribute separators.
788 789 790 |
# File 'lib/action_controller/routing.rb', line 788 def separators @separators end |
Instance Method Details
#assign_default_route_options(segments) ⇒ Object
Assign default options, such as ‘index’ as a default for :action. This method must be run after user supplied requirements and defaults have been applied to the segments.
899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 |
# File 'lib/action_controller/routing.rb', line 899 def (segments) segments.each do |segment| next unless segment.is_a? DynamicSegment case segment.key when :action if segment.regexp.nil? || segment.regexp.match('index').to_s == 'index' segment.default ||= 'index' segment.is_optional = true end when :id if segment.default.nil? && segment.regexp.nil? || segment.regexp =~ '' segment.is_optional = true end end end end |
#assign_route_options(segments, defaults, requirements) ⇒ Object
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.
864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 |
# File 'lib/action_controller/routing.rb', line 864 def (segments, defaults, requirements) route_requirements = {} # Requirements that do not belong to a segment segment_named = Proc.new do |key| segments.detect { |segment| segment.key == key if segment.respond_to?(:key) } end requirements.each do |key, requirement| segment = segment_named[key] if segment raise TypeError, "#{key}: requirements on a path segment must be regular expressions" unless requirement.is_a?(Regexp) if requirement.source =~ %r{\A(\\A|\^)|(\\Z|\\z|\$)\Z} raise ArgumentError, "Regexp anchor characters are not allowed in routing requirements: #{requirement.inspect}" end segment.regexp = requirement else route_requirements[key] = requirement end end defaults.each do |key, default| segment = segment_named[key] raise ArgumentError, "#{key}: No matching segment exists; cannot assign default" unless segment segment.is_optional = true segment.default = default.to_param if default end (segments) ensure_required_segments(segments) route_requirements end |
#build(path, options) ⇒ Object
Construct and return a route with the given path and options.
936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 |
# File 'lib/action_controller/routing.rb', line 936 def build(path, ) # Wrap the path with slashes path = "/#{path}" unless path[0] == ?/ path = "#{path}/" unless path[-1] == ?/ segments = segments_for_route_path(path) defaults, requirements, conditions = (segments, ) requirements = (segments, defaults, requirements) route = Route.new route.segments = segments route.requirements = requirements route.conditions = conditions if !route.significant_keys.include?(:action) && !route.requirements[:action] route.requirements[:action] = "index" route.significant_keys << :action end if !route.significant_keys.include?(:controller) raise ArgumentError, "Illegal route: the :controller must be specified!" end route end |
#divide_route_options(segments, options) ⇒ Object
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.
846 847 848 849 850 851 852 853 854 855 856 857 858 859 |
# File 'lib/action_controller/routing.rb', line 846 def (segments, ) = .dup requirements = (.delete(:requirements) || {}).dup defaults = (.delete(:defaults) || {}).dup conditions = (.delete(:conditions) || {}).dup path_keys = segments.collect { |segment| segment.key if segment.respond_to?(:key) }.compact .each do |key, value| hash = (path_keys.include?(key) && ! value.is_a?(Regexp)) ? defaults : requirements hash[key] = value end [defaults, requirements, conditions] end |
#ensure_required_segments(segments) ⇒ Object
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.
919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 |
# File 'lib/action_controller/routing.rb', line 919 def ensure_required_segments(segments) allow_optional = true segments.reverse_each do |segment| allow_optional &&= segment.optional? if !allow_optional && segment.optional? unless segment.optionality_implied? warn "Route segment \"#{segment.to_s}\" cannot be optional because it precedes a required segment. This segment will be required." end segment.is_optional = false elsif allow_optional & segment.respond_to?(:default) && segment.default # if a segment has a default, then it is optional segment.is_optional = true end end end |
#interval_regexp ⇒ Object
799 800 801 |
# File 'lib/action_controller/routing.rb', line 799 def interval_regexp Regexp.new "(.*?)(#{separators.source}|$)" end |
#segment_for(string) ⇒ Object
A factory method that returns a new segment instance appropriate for the format of the given string.
821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 |
# File 'lib/action_controller/routing.rb', line 821 def segment_for(string) segment = case string when /\A:(\w+)/ key = $1.to_sym case key when :controller then ControllerSegment.new(key) else DynamicSegment.new key end when /\A\*(\w+)/ then PathSegment.new($1.to_sym, :optional => true) when /\A\?(.*?)\?/ returning segment = StaticSegment.new($1) do segment.is_optional = true end when /\A(#{separator_pattern(:inverted)}+)/ then StaticSegment.new($1) when Regexp.new(separator_pattern) then returning segment = DividerSegment.new($&) do segment.is_optional = (optional_separators.include? $&) end end [segment, $~.post_match] end |
#segments_for_route_path(path) ⇒ Object
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.
809 810 811 812 813 814 815 816 817 |
# File 'lib/action_controller/routing.rb', line 809 def segments_for_route_path(path) rest, segments = path, [] until rest.empty? segment, rest = segment_for rest segments << segment end segments end |