diff --git a/actionpack/lib/action_controller/metal/exceptions.rb b/actionpack/lib/action_controller/metal/exceptions.rb index a65857d6ef..1cccb51088 100644 --- a/actionpack/lib/action_controller/metal/exceptions.rb +++ b/actionpack/lib/action_controller/metal/exceptions.rb @@ -50,4 +50,7 @@ module ActionController class UnknownFormat < ActionControllerError #:nodoc: end + + class MissingExactTemplate < UnknownFormat #:nodoc: + end end diff --git a/actionpack/lib/action_controller/metal/implicit_render.rb b/actionpack/lib/action_controller/metal/implicit_render.rb index ac0c127cdc..d3bb58f48b 100644 --- a/actionpack/lib/action_controller/metal/implicit_render.rb +++ b/actionpack/lib/action_controller/metal/implicit_render.rb @@ -41,18 +41,8 @@ module ActionController raise ActionController::UnknownFormat, message elsif interactive_browser_request? - message = "#{self.class.name}\##{action_name} is missing a template " \ - "for this request format and variant.\n\n" \ - "request.formats: #{request.formats.map(&:to_s).inspect}\n" \ - "request.variant: #{request.variant.inspect}\n\n" \ - "NOTE! For XHR/Ajax or API requests, this action would normally " \ - "respond with 204 No Content: an empty white screen. Since you're " \ - "loading it in a web browser, we assume that you expected to " \ - "actually render a template, not nothing, so we're showing an " \ - "error to be extra-clear. If you expect 204 No Content, carry on. " \ - "That's what you'll get from an XHR or API request. Give it a shot." - - raise ActionController::UnknownFormat, message + message = "#{self.class.name}\##{action_name} is missing a template for request formats: #{request.formats.map(&:to_s).join(',')}" + raise ActionController::MissingExactTemplate, message else logger.info "No template found for #{self.class.name}\##{action_name}, rendering head :no_content" if logger super diff --git a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb index d1b4508378..f05c69137b 100644 --- a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb +++ b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb @@ -12,6 +12,7 @@ module ActionDispatch "ActionController::UnknownHttpMethod" => :method_not_allowed, "ActionController::NotImplemented" => :not_implemented, "ActionController::UnknownFormat" => :not_acceptable, + "ActionController::MissingExactTemplate" => :not_acceptable, "ActionController::InvalidAuthenticityToken" => :unprocessable_entity, "ActionController::InvalidCrossOriginRequest" => :unprocessable_entity, "ActionDispatch::Http::Parameters::ParseError" => :bad_request, @@ -22,11 +23,12 @@ module ActionDispatch ) cattr_accessor :rescue_templates, default: Hash.new("diagnostics").merge!( - "ActionView::MissingTemplate" => "missing_template", - "ActionController::RoutingError" => "routing_error", - "AbstractController::ActionNotFound" => "unknown_action", - "ActiveRecord::StatementInvalid" => "invalid_statement", - "ActionView::Template::Error" => "template_error" + "ActionView::MissingTemplate" => "missing_template", + "ActionController::RoutingError" => "routing_error", + "AbstractController::ActionNotFound" => "unknown_action", + "ActiveRecord::StatementInvalid" => "invalid_statement", + "ActionView::Template::Error" => "template_error", + "ActionController::MissingExactTemplate" => "missing_exact_template", ) attr_reader :backtrace_cleaner, :exception, :line_number, :file diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb new file mode 100644 index 0000000000..3621ea81de --- /dev/null +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb @@ -0,0 +1,19 @@ +
+

No template for interactive request

+
+ +
+

<%= h @exception.message %>

+ +

+ NOTE!
+ Unless told otherwise, Rails expects an action to render a template with the same name,
+ contained in a folder named after its controller. + + If this controller is an API responding with 204 (No Content),
+ which does not require a template, + then this error will occur when trying to access it via browser,
+ since we expect an HTML template + to be rendered for such requests. If that's the case, carry on. +

+
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb new file mode 100644 index 0000000000..fcdbe6069d --- /dev/null +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb @@ -0,0 +1,3 @@ +Missing exact template + +<%= @exception.message %> diff --git a/actionpack/test/controller/mime/respond_to_test.rb b/actionpack/test/controller/mime/respond_to_test.rb index f9ffd5f54c..771eccb29b 100644 --- a/actionpack/test/controller/mime/respond_to_test.rb +++ b/actionpack/test/controller/mime/respond_to_test.rb @@ -658,13 +658,13 @@ class RespondToControllerTest < ActionController::TestCase end def test_variant_without_implicit_rendering_from_browser - assert_raises(ActionController::UnknownFormat) do + assert_raises(ActionController::MissingExactTemplate) do get :variant_without_implicit_template_rendering, params: { v: :does_not_matter } end end def test_variant_variant_not_set_and_without_implicit_rendering_from_browser - assert_raises(ActionController::UnknownFormat) do + assert_raises(ActionController::MissingExactTemplate) do get :variant_without_implicit_template_rendering end end diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index fc21543049..24c5761e41 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -650,7 +650,7 @@ class ImplicitRenderTest < ActionController::TestCase tests ImplicitRenderTestController def test_implicit_no_content_response_as_browser - assert_raises(ActionController::UnknownFormat) do + assert_raises(ActionController::MissingExactTemplate) do get :empty_action end end