Skip to content

Commit

Permalink
Merge pull request rails#26672 from schpet/support_ruby_keywords_as_t…
Browse files Browse the repository at this point in the history
…emplate_locals

Avoid compiling ruby keywords into template locals
  • Loading branch information
matthewd authored Oct 2, 2016
2 parents 832b026 + f9960f2 commit 7b63f56
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 1 deletion.
18 changes: 18 additions & 0 deletions actionview/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
* Render now accepts any keys for locals, including reserved words

Only locals with valid variable names get set directly. Others
will still be available in local_assigns.

Example of render with reserved words:

```erb
<%= render "example", class: "text-center", message: "Hello world!" %>
<!-- _example.html.erb: -->
<%= tag.div class: local_assigns[:class] do %>
<p><%= message %></p>
<% end %>
```
*Peter Schilling*, *Matthew Draper*
* Show cache hits and misses when rendering partials.
Partials using the `cache` helper will show whether a render hit or missed
Expand Down
8 changes: 7 additions & 1 deletion actionview/lib/action_view/template.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require "active_support/core_ext/object/try"
require "active_support/core_ext/kernel/singleton_class"
require "active_support/core_ext/module/delegation"
require "thread"

module ActionView
Expand Down Expand Up @@ -324,8 +325,13 @@ def handle_render_error(view, e) #:nodoc:
end

def locals_code #:nodoc:
# Only locals with valid variable names get set directly. Others will
# still be available in local_assigns.
locals = @locals.to_set - Module::DELEGATION_RESERVED_METHOD_NAMES
locals = locals.grep(/\A(?![A-Z0-9])(?:[[:alnum:]_]|[^\0-\177])+\z/)

# Double assign to suppress the dreaded 'assigned but unused variable' warning
@locals.each_with_object("") { |key, code| code << "#{key} = #{key} = local_assigns[:#{key}];" }
locals.each_with_object("") { |key, code| code << "#{key} = #{key} = local_assigns[:#{key}];" }
end

def method_name #:nodoc:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<%= local_assigns.inspect.html_safe %>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<%= 🎃 %>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The class is <%= local_assigns[:class] %>
19 changes: 19 additions & 0 deletions actionview/test/template/compiled_templates_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,25 @@ def test_template_with_nil_erb_return
assert_equal "This is nil: \n", render(template: "test/nil_return")
end

def test_template_with_ruby_keyword_locals
assert_equal "The class is foo",
render(file: "test/render_file_with_ruby_keyword_locals", locals: { class: "foo" })
end

def test_template_with_invalid_identifier_locals
locals = {
foo: "bar",
Foo: "bar",
"d-a-s-h-e-s": "",
"white space": "",
}
assert_equal locals.inspect, render(file: "test/render_file_inspect_local_assigns", locals: locals)
end

def test_template_with_unicode_identifier
assert_equal "🎂", render(file: "test/render_file_unicode_local", locals: { 🎃: "🎂" })
end

def test_template_gets_recompiled_when_using_different_keys_in_local_assigns
assert_equal "one", render(file: "test/render_file_with_locals_and_default")
assert_equal "two", render(file: "test/render_file_with_locals_and_default", locals: { secret: "two" })
Expand Down

0 comments on commit 7b63f56

Please sign in to comment.