class ActionDispatch::Routing::RouteSet
:nodoc:
def self.default_resources_path_names
def self.default_resources_path_names { :new => 'new', :edit => 'edit' } end
def _generate_prefix(options = {})
def _generate_prefix(options = {}) nil end
def add_route(app, conditions = {}, requirements = {}, defaults = {}, name = nil, anchor = true)
def add_route(app, conditions = {}, requirements = {}, defaults = {}, name = nil, anchor = true) raise ArgumentError, "Invalid route name: '#{name}'" unless name.blank? || name.to_s.match(/^[_a-z]\w*$/i) path = build_path(conditions.delete(:path_info), requirements, SEPARATORS, anchor) conditions = build_conditions(conditions, valid_conditions, path.names.map { |x| x.to_sym }) route = @set.add_route(app, path, conditions, defaults, name) named_routes[name] = route if name route end
def append(&block)
def append(&block) @append << block end
def build_conditions(current_conditions, req_predicates, path_values)
def build_conditions(current_conditions, req_predicates, path_values) conditions = current_conditions.dup verbs = conditions[:request_method] || [] # Rack-Mount requires that :request_method be a regular expression. # :request_method represents the HTTP verb that matches this route. # # Here we munge values before they get sent on to rack-mount. unless verbs.empty? conditions[:request_method] = %r[^#{verbs.join('|')}$] end conditions.delete_if { |k,v| !(req_predicates.include?(k) || path_values.include?(k)) } conditions end
def build_path(path, requirements, separators, anchor)
def build_path(path, requirements, separators, anchor) strexp = Journey::Router::Strexp.new( path, requirements, SEPARATORS, anchor) pattern = Journey::Path::Pattern.new(strexp) builder = Journey::GTG::Builder.new pattern.spec # Get all the symbol nodes followed by literals that are not the # dummy node. symbols = pattern.spec.grep(Journey::Nodes::Symbol).find_all { |n| builder.followpos(n).first.literal? } # Get all the symbol nodes preceded by literals. symbols.concat pattern.spec.find_all(&:literal?).map { |n| builder.followpos(n).first }.find_all(&:symbol?) symbols.each { |x| x.regexp = /(?:#{Regexp.union(x.regexp, '-')})+/ } pattern end
def call(env)
def call(env) finalize! @router.call(env) end
def clear!
def clear! @finalized = false named_routes.clear set.clear formatter.clear @prepend.each { |blk| eval_block(blk) } end
def define_mounted_helper(name)
def define_mounted_helper(name) return if MountedHelpers.method_defined?(name) routes = self MountedHelpers.class_eval do define_method "_#{name}" do RoutesProxy.new(routes, self._routes_context) end end MountedHelpers.class_eval <<-RUBY def #{name} @#{name} ||= _#{name} end RUBY end
def draw(&block)
def draw(&block) clear! unless @disable_clear_and_finalize eval_block(block) finalize! unless @disable_clear_and_finalize nil end
def empty?
def empty? routes.empty? end
def eval_block(block)
def eval_block(block) if block.arity == 1 raise "You are using the old router DSL which has been removed in Rails 3.1. " << "Please check how to update your routes file at: http://www.engineyard.com/blog/2010/the-lowdown-on-routes-in-rails-3/" end mapper = Mapper.new(self) if default_scope mapper.with_default_scope(default_scope, &block) else mapper.instance_exec(&block) end end
def extra_keys(options, recall={})
Generate the path indicated by the arguments, and return an array of
def extra_keys(options, recall={}) generate_extras(options, recall).last end
def extract_authentication(options)
def extract_authentication(options) if options[:user] && options[:password] [options.delete(:user), options.delete(:password)] else nil end end
def finalize!
def finalize! return if @finalized @append.each { |blk| eval_block(blk) } @finalized = true end
def generate(options, recall = {}, extras = false)
def generate(options, recall = {}, extras = false) Generator.new(options, recall, self, extras).generate end
def generate_extras(options, recall={})
def generate_extras(options, recall={}) generate(options, recall, true) end
def handle_positional_args(options)
def handle_positional_args(options) return unless args = options.delete(:_positional_args) keys = options.delete(:_positional_keys) keys -= options.keys if args.size < keys.size - 1 # take format into account # Tell url_for to skip default_url_options options.merge!(Hash[args.zip(keys).map { |v, k| [k, v] }]) end
def initialize(request_class = ActionDispatch::Request)
def initialize(request_class = ActionDispatch::Request) self.named_routes = NamedRouteCollection.new self.resources_path_names = self.class.default_resources_path_names.dup self.default_url_options = {} self.request_class = request_class @valid_conditions = {} request_class.public_instance_methods.each { |m| @valid_conditions[m.to_sym] = true } @valid_conditions[:controller] = true @valid_conditions[:action] = true self.valid_conditions.delete(:id) @append = [] @prepend = [] @disable_clear_and_finalize = false @finalized = false @set = Journey::Routes.new @router = Journey::Router.new(@set, { :parameters_key => PARAMETERS_KEY, :request_class => request_class}) @formatter = Journey::Formatter.new @set end
def install_helpers(destinations = [ActionController::Base, ActionView::Base], regenerate_code = false)
def install_helpers(destinations = [ActionController::Base, ActionView::Base], regenerate_code = false) Array(destinations).each { |d| d.module_eval { include Helpers } } named_routes.install(destinations, regenerate_code) end
def mounted_helpers
def mounted_helpers MountedHelpers end
def prepend(&block)
def prepend(&block) @prepend << block end
def recognize_path(path, environment = {})
def recognize_path(path, environment = {}) method = (environment[:method] || "GET").to_s.upcase path = Journey::Router::Utils.normalize_path(path) unless path =~ %r{://} extras = environment[:extras] || {} begin env = Rack::MockRequest.env_for(path, {:method => method, :params => extras}) rescue URI::InvalidURIError => e raise ActionController::RoutingError, e.message end req = @request_class.new(env) @router.recognize(req) do |route, matches, params| params.each do |key, value| if value.is_a?(String) value = value.dup.force_encoding(Encoding::BINARY) if value.encoding_aware? params[key] = URI.parser.unescape(value) end end dispatcher = route.app while dispatcher.is_a?(Mapper::Constraints) && dispatcher.matches?(env) do dispatcher = dispatcher.app end if dispatcher.is_a?(Dispatcher) && dispatcher.controller(params, false) dispatcher.prepare_params!(params) return params end end raise ActionController::RoutingError, "No route matches #{path.inspect}" end
def url_for(options)
def url_for(options) finalize! options = (options || {}).reverse_merge!(default_url_options) handle_positional_args(options) user, password = extract_authentication(options) path_segments = options.delete(:_path_segments) script_name = options.delete(:script_name) path = (script_name.blank? ? _generate_prefix(options) : script_name.chomp('/')).to_s path_options = options.except(*RESERVED_OPTIONS) path_options = yield(path_options) if block_given? path_addition, params = generate(path_options, path_segments || {}) path << path_addition params.merge!(options[:params] || {}) ActionDispatch::Http::URL.url_for(options.merge!({ :path => path, :params => params, :user => user, :password => password })) end
def url_helpers
def url_helpers @url_helpers ||= begin routes = self helpers = Module.new do extend ActiveSupport::Concern include UrlFor @_routes = routes class << self delegate :url_for, :to => '@_routes' end extend routes.named_routes.module # ROUTES TODO: install_helpers isn't great... can we make a module with the stuff that # we can include? # Yes plz - JP included do routes.install_helpers(self) singleton_class.send(:redefine_method, :_routes) { routes } end define_method(:_routes) { @_routes || routes } end helpers end end