Use TOPLEVEL_BINDING in rails runner command

Binding to capture the local scope. This means that if a constant with same
name as constant specified by the user exists in local scope, constant
defined in local will use. This is different from what the user expects.
Therefore, fixed to use top-level binding instead of local scope.

Fixes #30644
This commit is contained in:
yuuji.yaginuma 2017-09-22 10:29:23 +09:00
parent 6c199967fc
commit daa592293b
2 changed files with 14 additions and 2 deletions

@ -32,13 +32,13 @@ def perform(code_or_file = nil, *command_argv)
ARGV.replace(command_argv)
if code_or_file == "-"
eval($stdin.read, binding, "stdin")
eval($stdin.read, TOPLEVEL_BINDING, "stdin")
elsif File.exist?(code_or_file)
$0 = code_or_file
Kernel.load code_or_file
else
begin
eval(code_or_file, binding, __FILE__, __LINE__)
eval(code_or_file, TOPLEVEL_BINDING, __FILE__, __LINE__)
rescue SyntaxError, NameError => error
$stderr.puts "Please specify a valid ruby command or the path of a script to run."
$stderr.puts "Run '#{self.class.executable} -h' for help."

@ -128,5 +128,17 @@ def test_environment_with_rack_env
assert_match "production", rails("runner", "puts Rails.env")
end
end
def test_can_call_same_name_class_as_defined_in_thor
app_file "app/models/task.rb", <<-MODEL
class Task
def self.count
42
end
end
MODEL
assert_match "42", rails("runner", "puts Task.count")
end
end
end