aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/erb.rb10
-rw-r--r--test/erb/test_erb.rb29
2 files changed, 39 insertions, 0 deletions
diff --git a/lib/erb.rb b/lib/erb.rb
index 4c29553a53..f367e32a97 100644
--- a/lib/erb.rb
+++ b/lib/erb.rb
@@ -889,6 +889,16 @@ class ERB
end
end
+ # Render a template on a new toplevel binding with local variables specified
+ # by a Hash object.
+ def result_with_hash(hash)
+ b = new_toplevel
+ hash.each_pair do |key, value|
+ b.local_variable_set(key, value)
+ end
+ result(b)
+ end
+
##
# Returns a new binding each time *near* TOPLEVEL_BINDING for runs that do
# not specify a binding.
diff --git a/test/erb/test_erb.rb b/test/erb/test_erb.rb
index 10fb177f58..c41ba25d7c 100644
--- a/test/erb/test_erb.rb
+++ b/test/erb/test_erb.rb
@@ -564,6 +564,35 @@ EOS
assert_equal(flag, erb.result)
end
end
+
+ def test_result_with_hash
+ erb = @erb.new("<%= foo %>")
+ assert_equal("1", erb.result_with_hash(foo: "1"))
+ end
+
+ def test_result_with_hash_does_not_use_caller_local_variables
+ erb = @erb.new("<%= foo %>")
+ foo = 1
+ assert_raise(NameError) { erb.result_with_hash({}) }
+ end
+
+ def test_result_with_hash_does_not_modify_caller_binding
+ erb = @erb.new("<%= foo %>")
+ erb.result_with_hash(foo: "1")
+ assert_equal(false, binding.local_variable_defined?(:foo))
+ end
+
+ def test_result_with_hash_does_not_modify_toplevel_binding
+ erb = @erb.new("<%= foo %>")
+ erb.result_with_hash(foo: "1")
+ assert_equal(false, TOPLEVEL_BINDING.local_variable_defined?(:foo))
+ end
+
+ # This depends on the behavior that #local_variable_set raises TypeError by invalid key.
+ def test_result_with_hash_with_invalid_keys_raises_type_error
+ erb = @erb.new("<%= 1 %>")
+ assert_raise(TypeError) { erb.result_with_hash({ 1 => "1" }) }
+ end
end
class TestERBCoreWOStrScan < TestERBCore