123456789_123456789_123456789_123456789_123456789_

Class: ActionDispatch::Routing::RouteSet::NamedRouteCollection::UrlHelper::OptimizedUrlHelper

Do not use. This class is for internal use only.
Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, UrlHelper
Instance Chain:
self, UrlHelper
Inherits: UrlHelper
  • ::Object
Defined in: actionpack/lib/action_dispatch/routing/route_set.rb

Constant Summary

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Constructor Details

.new(route, options, route_name) ⇒ OptimizedUrlHelper

[ GitHub ]

  
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 206

def initialize(route, options, route_name)
  super
  @required_parts = @route.required_parts
  @arg_size       = @required_parts.size
  # The general path omits a format equal to the route's default, and fills
  # optional segments before the format from the current request.
  @format_optimizable = !route.defaults.key?(:format) && @segment_keys - @required_parts == [:format]
  # As in the general path, a trailing slash isn't added after a format,
  # including a format passed as a required segment.
  @format_required = @required_parts.include?(:format)
  # With options, the general path assigns positional arguments to all
  # segment keys in order, so an optional segment before a required one
  # (as in <tt>scope "(:locale)"</tt>) would take the first argument.
  @options_optimizable = @segment_keys.first(@arg_size) == @required_parts &&
    !@segment_keys.intersect?(RESERVED_OPTIONS)
  # As in the general path, only required segments are checked against
  # the route's requirements.
  @requirements = route.path.requirements_for_missing_keys_check.slice(*@required_parts)
  @requirements = nil if @requirements.empty?
end

Instance Attribute Details

#arg_size (readonly)

[ GitHub ]

  
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 204

attr_reader :arg_size

Instance Method Details

#call(t, method_name, args, inner_options, url_strategy)

[ GitHub ]

  
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 227

def call(t, method_name, args, inner_options, url_strategy)
  if args.size == arg_size && optimizable_options?(inner_options) && optimize_routes_generation?(t) &&
      (@options_optimizable || !default_url_options?(t))
    options = t.url_options.merge @options
    # As in RouteSet#url_for, the route set's default URL options come last.
    route_set_defaults = t._routes.default_url_options
    options = route_set_defaults.merge(options) unless route_set_defaults.empty?
    format = inner_options && inner_options[:format]
    path = optimized_helper(args, format)
    if path.nil?
      # With options, a missing argument raises the general path's error,
      # as does any argument that fails a requirement.
      return super if inner_options || @requirements
      raise_generation_error(args)
    end
    merge_url_and_query_options!(options, inner_options) if inner_options && !sole_format?(inner_options)
    path << "/" if options[:trailing_slash] && !format && !@format_required && !options[:format] && !path.end_with?("/")
    options[:path] = path

    original_script_name = options.delete(:original_script_name)
    script_name = t._routes.find_script_name(options)

    if original_script_name
      script_name = original_script_name + script_name
    end

    options[:script_name] = script_name

    url_strategy.call options
  else
    super
  end
end

#default_url_options?(t) ⇒ Boolean (private)

Whether default URL options apply, which the general path handles differently on routes whose options aren't optimizable.

[ GitHub ]

  
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 312

def default_url_options?(t)
  !t._routes.default_url_options.empty? ||
    (t.respond_to?(:default_url_options, true) && !t.send(:default_url_options).empty?)
end

#general_path_option?(key) ⇒ Boolean (private)

[ GitHub ]

  
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 276

def general_path_option?(key)
  @segment_keys.include?(key) || @options.key?(key) || GENERAL_PATH_OPTIONS.include?(key)
end

#merge_url_and_query_options!(options, inner_options) (private)

As in the general path, every other option becomes a query parameter.

[ GitHub ]

  
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 281

def merge_url_and_query_options!(options, inner_options)
  query_params = nil
  inner_options.each do |key, value|
    if key == :format || RESERVED_OPTIONS.include?(key)
      options[key] = value
    else
      (query_params ||= {})[key] = value
    end
  end
  options[:params] = query_params if query_params
end

#optimizable_options?(inner_options) ⇒ Boolean (private)

[ GitHub ]

  
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 262

def optimizable_options?(inner_options)
  return true if inner_options.nil?
  return false unless @options_optimizable
  return @format_optimizable && inner_options[:format] if sole_format?(inner_options)

  !inner_options.any? do |key, value|
    key == :format ? !(@format_optimizable && value) : general_path_option?(key)
  end
end

#optimize_routes_generation?(t) ⇒ Boolean (private)

[ GitHub ]

  
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 306

def optimize_routes_generation?(t)
  t.send(:optimize_routes_generation?)
end

#optimized_helper(args, format = nil) (private)

[ GitHub ]

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

def optimized_helper(args, format = nil)
  params = parameterize_args(args) { return }
  return if @requirements && !@requirements.all? { |key, test| test.match?(params[key]) }
  if format
    # As in the general path, a blank format is dropped rather than
    # rendered as a trailing dot.
    format = format.to_param
    params[:format] = format if format.present?
  end

  @route.format params
end

#parameterize_args(args) (private)

[ GitHub ]

  
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 317

def parameterize_args(args)
  params = {}
  @arg_size.times { |i|
    key = @required_parts[i]
    value = args[i].to_param
    yield key if value.nil? || value.empty?
    params[key] = value
  }
  params
end

#raise_generation_error(args) (private)

[ GitHub ]

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

def raise_generation_error(args)
  missing_keys = []
  params = parameterize_args(args) { |missing_key|
    missing_keys << missing_key
  }
  constraints = Hash[@route.requirements.merge(params).sort_by { |k, v| k.to_s }]
  message = +"No route matches #{constraints.inspect}"
  message << ", missing required keys: #{missing_keys.sort.inspect}"

  raise ActionController::UrlGenerationError, message
end

#sole_format?(inner_options) ⇒ Boolean (private)

[ GitHub ]

  
# File 'actionpack/lib/action_dispatch/routing/route_set.rb', line 272

def sole_format?(inner_options)
  inner_options.size == 1 && inner_options.key?(:format)
end