Class: ActionDispatch::Routing::RouteSet

Inherits:
Object
  • Object
show all
Defined in:
actionpack/lib/action_dispatch/routing/route_set.rb

Overview

:nodoc:

Defined Under Namespace

Modules: MountedHelpers Classes: Dispatcher, Generator, NamedRouteCollection

Constant Summary collapse

PARAMETERS_KEY =
'action_dispatch.request.path_parameters'
RESERVED_OPTIONS =
[:host, :protocol, :port, :subdomain, :domain, :tld_length,
:trailing_slash, :anchor, :params, :only_path, :script_name,
:original_script_name]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(request_class = ActionDispatch::Request) ⇒ RouteSet


299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 299

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

  @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

Instance Attribute Details

#default_scopeObject

Returns the value of attribute default_scope


289
290
291
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 289

def default_scope
  @default_scope
end

#default_url_optionsObject

Returns the value of attribute default_url_options


291
292
293
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 291

def default_url_options
  @default_url_options
end

#disable_clear_and_finalizeObject

Returns the value of attribute disable_clear_and_finalize


290
291
292
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 290

def disable_clear_and_finalize
  @disable_clear_and_finalize
end

#formatterObject

Returns the value of attribute formatter


289
290
291
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 289

def formatter
  @formatter
end

#named_routesObject

Returns the value of attribute named_routes


289
290
291
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 289

def named_routes
  @named_routes
end

#request_classObject

Returns the value of attribute request_class


291
292
293
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 291

def request_class
  @request_class
end

#resources_path_namesObject

Returns the value of attribute resources_path_names


290
291
292
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 290

def resources_path_names
  @resources_path_names
end

#routerObject

Returns the value of attribute router


289
290
291
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 289

def router
  @router
end

#setObject Also known as: routes

Returns the value of attribute set


289
290
291
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 289

def set
  @set
end

Class Method Details

.default_resources_path_namesObject


295
296
297
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 295

def self.default_resources_path_names
  { :new => 'new', :edit => 'edit' }
end

Instance Method Details

#_generate_prefix(options = {}) ⇒ Object


648
649
650
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 648

def _generate_prefix(options = {})
  nil
end

#add_route(app, conditions = {}, requirements = {}, defaults = {}, name = nil, anchor = true) ⇒ Object

Raises:

  • (ArgumentError)

430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 430

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)

  if name && named_routes[name]
    raise ArgumentError, "Invalid route name, already in use: '#{name}' \n" \
      "You may have defined two routes with the same name using the `:as` option, or " \
      "you may be overriding a route already defined by a resource with the same naming. " \
      "For the latter, you can restrict the routes created with `resources` as explained here: \n" \
      "http://guides.rubyonrails.org/routing.html#restricting-the-routes-created"
  end

  path = build_path(conditions.delete(:path_info), requirements, SEPARATORS, anchor)
  conditions = build_conditions(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

#append(&block) ⇒ Object


324
325
326
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 324

def append(&block)
  @append << block
end

#call(env) ⇒ Object


681
682
683
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 681

def call(env)
  @router.call(env)
end

#clear!Object


351
352
353
354
355
356
357
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 351

def clear!
  @finalized = false
  named_routes.clear
  set.clear
  formatter.clear
  @prepend.each { |blk| eval_block(blk) }
end

#define_mounted_helper(name) ⇒ Object


372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 372

def define_mounted_helper(name)
  return if MountedHelpers.method_defined?(name)

  routes = self
  MountedHelpers.class_eval do
    define_method "_#{name}" do
      RoutesProxy.new(routes, _routes_context)
    end
  end

  MountedHelpers.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
    def #{name}
      @_#{name} ||= _#{name}
    end
  RUBY
end

#draw(&block) ⇒ Object


317
318
319
320
321
322
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 317

def draw(&block)
  clear! unless @disable_clear_and_finalize
  eval_block(block)
  finalize! unless @disable_clear_and_finalize
  nil
end

#empty?Boolean


426
427
428
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 426

def empty?
  routes.empty?
end

#eval_block(block) ⇒ Object


332
333
334
335
336
337
338
339
340
341
342
343
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 332

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

#extra_keys(options, recall = {}) ⇒ Object

Generate the path indicated by the arguments, and return an array of the keys that were not used to generate it.


623
624
625
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 623

def extra_keys(options, recall={})
  generate_extras(options, recall).last
end

#finalize!Object


345
346
347
348
349
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 345

def finalize!
  return if @finalized
  @append.each { |blk| eval_block(blk) }
  @finalized = true
end

#generate(options, recall = {}) ⇒ Object


632
633
634
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 632

def generate(options, recall = {})
  Generator.new(options, recall, self).generate
end

#generate_extras(options, recall = {}) ⇒ Object


627
628
629
630
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 627

def generate_extras(options, recall={})
  path, params = generate(options, recall)
  return path, params.keys
end

#mounted?Boolean


640
641
642
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 640

def mounted?
  false
end

#mounted_helpersObject

Contains all the mounted helpers accross different engines and the `main_app` helper for the application. You can include this in your classes if you want to access routes for other engines.


368
369
370
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 368

def mounted_helpers
  MountedHelpers
end

#optimize_routes_generation?Boolean


644
645
646
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 644

def optimize_routes_generation?
  !mounted? && default_url_options.empty?
end

#prepend(&block) ⇒ Object


328
329
330
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 328

def prepend(&block)
  @prepend << block
end

#recognize_path(path, environment = {}) ⇒ Object


685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 685

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})
  rescue URI::InvalidURIError => e
    raise ActionController::RoutingError, e.message
  end

  req = @request_class.new(env)
  @router.recognize(req) do |route, _matches, params|
    params.merge!(extras)
    params.each do |key, value|
      if value.is_a?(String)
        value = value.dup.force_encoding(Encoding::BINARY)
        params[key] = URI.parser.unescape(value)
      end
    end
    old_params = env[::ActionDispatch::Routing::RouteSet::PARAMETERS_KEY]
    env[::ActionDispatch::Routing::RouteSet::PARAMETERS_KEY] = (old_params || {}).merge(params)
    dispatcher = route.app
    while dispatcher.is_a?(Mapper::Constraints) && dispatcher.matches?(env) do
      dispatcher = dispatcher.app
    end

    if dispatcher.is_a?(Dispatcher)
      if dispatcher.controller(params, false)
        dispatcher.prepare_params!(params)
        return params
      else
        raise ActionController::RoutingError, "A route matches #{path.inspect}, but references missing controller: #{params[:controller].camelize}Controller"
      end
    end
  end

  raise ActionController::RoutingError, "No route matches #{path.inspect}"
end

#url_for(options) ⇒ Object

The options argument must be nil or a hash whose keys are symbols.


653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 653

def url_for(options)
  options = default_url_options.merge(options || {})

  user, password = extract_authentication(options)
  recall  = options.delete(:_recall)

  original_script_name = options.delete(:original_script_name).presence
  script_name = options.delete(:script_name).presence || _generate_prefix(options)

  if script_name && original_script_name
    script_name = original_script_name + script_name
  end

  path_options = options.except(*RESERVED_OPTIONS)
  path_options = yield(path_options) if block_given?

  path, params = generate(path_options, recall || {})
  params.merge!(options[:params] || {})

  ActionDispatch::Http::URL.url_for(options.merge!({
    :path => path,
    :script_name => script_name,
    :params => params,
    :user => user,
    :password => password
  }))
end

#url_helpersObject


389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 389

def url_helpers
  @url_helpers ||= begin
    routes = self

    Module.new do
      extend ActiveSupport::Concern
      include UrlFor

      # Define url_for in the singleton level so one can do:
      # Rails.application.routes.url_helpers.url_for(args)
      @_routes = routes
      class << self
        delegate :url_for, :optimize_routes_generation?, :to => '@_routes'
      end

      # Make named_routes available in the module singleton
      # as well, so one can do:
      # Rails.application.routes.url_helpers.posts_path
      extend routes.named_routes.module

      # Any class that includes this module will get all
      # named routes...
      include routes.named_routes.module

      # plus a singleton class method called _routes ...
      included do
        singleton_class.send(:redefine_method, :_routes) { routes }
      end

      # And an instance method _routes. Note that
      # UrlFor (included in this module) add extra
      # conveniences for working with @_routes.
      define_method(:_routes) { @_routes || routes }
    end
  end
end