aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch/routing
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_dispatch/routing')
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb51
1 files changed, 39 insertions, 12 deletions
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index 3ae9f92c0b..943fc15026 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -186,10 +186,16 @@ module ActionDispatch
klass = Journey::Router::Utils
@path_parts.zip(args) do |part, arg|
+ parameterized_arg = arg.to_param
+
+ if parameterized_arg.nil? || parameterized_arg.empty?
+ raise_generation_error(args)
+ end
+
# Replace each route parameter
# e.g. :id for regular parameter or *path for globbing
# with ruby string interpolation code
- path.gsub!(/(\*|:)#{part}/, klass.escape_fragment(arg.to_param))
+ path.gsub!(/(\*|:)#{part}/, klass.escape_fragment(parameterized_arg))
end
path
end
@@ -197,6 +203,25 @@ module ActionDispatch
def optimize_routes_generation?(t)
t.send(:optimize_routes_generation?)
end
+
+ def raise_generation_error(args)
+ parts, missing_keys = [], []
+
+ @path_parts.zip(args) do |part, arg|
+ parameterized_arg = arg.to_param
+
+ if parameterized_arg.nil? || parameterized_arg.empty?
+ missing_keys << part
+ end
+
+ parts << [part, arg]
+ end
+
+ message = "No route matches #{Hash[parts].inspect}"
+ message << " missing required keys: #{missing_keys.inspect}"
+
+ raise ActionController::UrlGenerationError, message
+ end
end
def initialize(route, options)
@@ -489,11 +514,12 @@ module ActionDispatch
@recall = recall.dup
@set = set
+ normalize_recall!
normalize_options!
normalize_controller_action_id!
use_relative_controller!
normalize_controller!
- handle_nil_action!
+ normalize_action!
end
def controller
@@ -512,6 +538,11 @@ module ActionDispatch
end
end
+ # Set 'index' as default action for recall
+ def normalize_recall!
+ @recall[:action] ||= 'index'
+ end
+
def normalize_options!
# If an explicit :controller was given, always make :action explicit
# too, so that action expiry works as expected for things like
@@ -527,8 +558,8 @@ module ActionDispatch
options[:controller] = options[:controller].to_s
end
- if options[:action]
- options[:action] = options[:action].to_s
+ if options.key?(:action)
+ options[:action] = (options[:action] || 'index').to_s
end
end
@@ -538,8 +569,6 @@ module ActionDispatch
# :controller, :action or :id is not found, don't pull any
# more keys from the recall.
def normalize_controller_action_id!
- @recall[:action] ||= 'index' if current_controller
-
use_recall_for(:controller) or return
use_recall_for(:action) or return
use_recall_for(:id)
@@ -561,13 +590,11 @@ module ActionDispatch
@options[:controller] = controller.sub(%r{^/}, '') if controller
end
- # This handles the case of action: nil being explicitly passed.
- # It is identical to action: "index"
- def handle_nil_action!
- if options.has_key?(:action) && options[:action].nil?
- options[:action] = 'index'
+ # Move 'index' action from options to recall
+ def normalize_action!
+ if @options[:action] == 'index'
+ @recall[:action] = @options.delete(:action)
end
- recall[:action] = options.delete(:action) if options[:action] == 'index'
end
# Generates a path from routes, returns [path, params].