Deprecate render locals to be assigned to instance variables

Rails partial rendering allows assigning instance variables.
For example:

  render 'partial', :@name => "Maceo"

This sets @name to "Maceo" on the ActionView::Base object.

The allowed instance variables aren't restricted to the user's defined
instance variables but can also override private Rails variables like
@_assigns, @output_buffer, @_config, and @_default_form_builder.
This commit is contained in:
Petrik 2021-02-16 19:20:21 +01:00
parent 1a60826c9d
commit 96d72d9b25
3 changed files with 15 additions and 1 deletions

View File

@ -1,3 +1,7 @@
* Deprecate `render` locals to be assigned to instance variables.
*Petrik de Heus*
* Remove legacy default `media=screen` from `stylesheet_link_tag`.
*André Luis Leal Cardoso Junior*

View File

@ -319,6 +319,13 @@ module ActionView
# Only locals with valid variable names get set directly. Others will
# still be available in local_assigns.
locals = @locals - Module::RUBY_RESERVED_KEYWORDS
deprecated_locals = locals.grep(/\A@+/)
if deprecated_locals.any?
ActiveSupport::Deprecation.warn(<<~MSG)
Passing instance variables to `render` is deprecated.
In Rails 7.0, #{deprecated_locals.to_sentence} will be ignored.
MSG
end
locals = locals.grep(/\A@?(?![A-Z0-9])(?:[[:alnum:]_]|[^\0-\177])+\z/)
# Assign for the same variable is to suppress unused variable warning

View File

@ -52,7 +52,10 @@ class CompiledTemplatesTest < ActiveSupport::TestCase
end
def test_template_with_instance_variable_identifier
assert_equal "bar", render(template: "test/render_file_instance_variable", locals: { "@foo": "bar" })
expected_deprecation = "In Rails 7.0, @foo will be ignored."
assert_deprecated(expected_deprecation) do
assert_equal "bar", render(template: "test/render_file_instance_variable", locals: { "@foo": "bar" })
end
end
def test_template_gets_recompiled_when_using_different_keys_in_local_assigns