Проблема здесь в том, что for
выражения цикла не создают новую область видимости. Единственные вещи, которые создают новые области в Ruby, это тела сценариев, тела модулей, тела классов, тела методов и блоки.
Если вы действительно посмотрите на поведение выражений цикла for
в черновой спецификации рубина ISO, вы обнаружите, что выражение цикла for
выполняется точно так же, как each
итератор , за исключением для тот факт, что он не создает новую область.
Ни один Rubyist никогда не использовал бы цикл for
, так или иначе: вместо этого они использовали бы итератор, который делает блок, и таким образом создает новую область видимости.
Если вы используете идиоматический итератор, все работает как положено:
class Object
%w[new create destroy].each do |name|
define_method "test_#{name}" do
puts name
end
end
end
require 'test/unit'
require 'stringio'
class TestDynamicMethods < Test::Unit::TestCase
def setup; @old_stdout, $> = $>, (@fake_logdest = StringIO.new) end
def teardown; $> = @old_stdout end
def test_that_the_test_create_method_prints_create
Object.new.test_create
assert_equal "create\n", @fake_logdest.string
end
def test_that_the_test_destroy_method_prints_destroy
Object.new.test_destroy
assert_equal "destroy\n", @fake_logdest.string
end
def test_that_the_test_new_method_prints_new
Object.new.test_new
assert_equal "new\n", @fake_logdest.string
end
end