New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Lock down new ImplicitRender
behavior for 5.0 RC
#23827
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
actionpack/lib/action_controller/metal/basic_implicit_render.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,29 +1,80 @@ | ||
require 'active_support/core_ext/string/strip' | ||
|
||
module ActionController | ||
# Handles implicit rendering for a controller action when it did not | ||
# explicitly indicate an appropiate response via methods such as +render+, | ||
# +respond_to+, +redirect+ or +head+. | ||
# | ||
# For API controllers, the implicit render always renders "204 No Content" | ||
# and does not account for any templates. | ||
# | ||
# For other controllers, the following conditions are checked: | ||
# | ||
# First, if a template exists for the controller action, it is rendered. | ||
# This template lookup takes into account the action name, locales, format, | ||
# variant, template handlers, etc. (see +render+ for details). | ||
# | ||
# Second, if other templates exist for the controller action but is not in | ||
# the right format (or variant, etc.), an <tt>ActionController::UnknownFormat</tt> | ||
# is raised. The list of available templates is assumed to be a complete | ||
# enumeration of all the possible formats (or variants, etc.); that is, | ||
# having only HTML and JSON templates indicate that the controller action is | ||
# not meant to handle XML requests. | ||
# | ||
# Third, if the current request is an "interactive" browser request (the user | ||
# navigated here by entering the URL in the address bar, submiting a form, | ||
# clicking on a link, etc. as opposed to an XHR or non-browser API request), | ||
# <tt>ActionView::UnknownFormat</tt> is raised to display a helpful error | ||
# message. | ||
# | ||
# Finally, it falls back to the same "204 No Content" behavior as API controllers. | ||
module ImplicitRender | ||
|
||
# :stopdoc: | ||
include BasicImplicitRender | ||
|
||
# Renders the template corresponding to the controller action, if it exists. | ||
# The action name, format, and variant are all taken into account. | ||
# For example, the "new" action with an HTML format and variant "phone" | ||
# would try to render the <tt>new.html+phone.erb</tt> template. | ||
# | ||
# If no template is found <tt>ActionController::BasicImplicitRender</tt>'s implementation is called, unless | ||
# a block is passed. In that case, it will override the super implementation. | ||
# | ||
# default_render do | ||
# head 404 # No template was found | ||
# end | ||
def default_render(*args) | ||
if template_exists?(action_name.to_s, _prefixes, variants: request.variant) | ||
render(*args) | ||
else | ||
if block_given? | ||
yield(*args) | ||
else | ||
logger.info "No template found for #{self.class.name}\##{action_name}, rendering head :no_content" if logger | ||
super | ||
elsif any_templates?(action_name.to_s, _prefixes) | ||
message = "#{self.class.name}\##{action_name} does not know how to repond " \ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. repond |
||
"to this request. There are other templates available for this controller " \ | ||
"action but none of them were suitable for this request.\n\n" \ | ||
"This usually happens when the client requested an unsupported format " \ | ||
"(e.g. requesting HTML content from a JSON endpoint or vice versa), but " \ | ||
"it might also be failing due to other constraints, such as locales or" \ | ||
"variants.\n" | ||
|
||
if request.formats.any? | ||
message << "\nRequested format(s): #{request.formats.join(", ")}" | ||
end | ||
|
||
if request.variant.any? | ||
message << "\nRequested variant(s): #{request.variant.join(", ")}" | ||
end | ||
|
||
raise ActionController::UnknownFormat, message | ||
elsif interactive_browser_request? | ||
message = "You did not define any templates for #{self.class.name}\##{action_name}. " \ | ||
"This is not necessarily a problem (e.g. you might be building an API endpoint " \ | ||
"that does not require any templates), and the controller would usually respond " \ | ||
"with `head :no_content` for your convenience.\n\n" \ | ||
"However, you appear to have navigated here from an interactive browser request – " \ | ||
"such as by navigating to this URL directly, clicking on a link or submitting a form. " \ | ||
"Rendering a `head :no_content` in this case could have resulted in unexpected UI " \ | ||
"behavior in the browser.\n\n" \ | ||
"If you expected the `head :no_content` response, you do not need to take any " \ | ||
"actions – requests coming from an XHR (AJAX) request or other non-browser clients " \ | ||
"will receive the \"204 No Content\" response as expected.\n\n" \ | ||
"If you did not expect this behavior, you can resolve this error by adding a " \ | ||
"template for this controller action (usually `#{action_name}.html.erb`) or " \ | ||
"otherwise indicate the appropriate response in the action using `render`, " \ | ||
"`redirect_to`, `head`, etc.\n" | ||
|
||
raise ActionController::UnknownFormat, message | ||
else | ||
logger.info "No template found for #{self.class.name}\##{action_name}, rendering head :no_content" if logger | ||
super | ||
end | ||
end | ||
|
||
|
@@ -32,5 +83,11 @@ def method_for_action(action_name) | |
"default_render" | ||
end | ||
end | ||
|
||
private | ||
|
||
def interactive_browser_request? | ||
request.format == Mime[:html] && !request.xhr? | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletions
1
...npack/test/fixtures/implicit_render_test/empty_action_with_mobile_variant.html+mobile.erb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
mobile |
1 change: 1 addition & 0 deletions
1
actionpack/test/fixtures/implicit_render_test/empty_action_with_template.html.erb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
<h1>Empty action rendered this implicitly.</h1> |
1 change: 1 addition & 0 deletions
1
actionpack/test/fixtures/implicit_render_test/some_action_2.html+zomg.erb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
zomg | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't see this file used for any tests. |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some of the docs felt a bit hard to read to me. Took a stab at rephrasing them.
Something feels funny about
assumed exhaustive
too, but ¯_(ツ)_/¯.Here's the originals: