From: Kazuki Tsujimoto Date: 2011-12-18T00:33:10+09:00 Subject: [ruby-dev:45003] [ruby-trunk - Bug #5731] enum_for を使うと method_missing にブロックが渡されない Issue #5731 has been updated by Kazuki Tsujimoto. =begin 今のmethod_missing関数の実装はpassed_blockを無条件に0クリアするようになっています。 同関数ではmethod_missingメソッドを呼び出す前に色々と処理を行っており その際にraiseされる可能性があるので0クリアしておくことは必要ですが、 前処理が終わった時点でpassed_blockを再設定しておかないといけないという話ではないかと思います。 以下のパッチでどうでしょうか。 diff --git a/vm_eval.c b/vm_eval.c index 44edf6f..d653e4e 100644 --- a/vm_eval.c +++ b/vm_eval.c @@ -563,6 +563,7 @@ method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status) { VALUE *nargv, result, argv_ary = 0; rb_thread_t *th = GET_THREAD(); + const rb_block_t *blockptr = th->passed_block; th->method_missing_reason = call_status; th->passed_block = 0; @@ -589,6 +590,7 @@ method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status) if (rb_method_basic_definition_p(CLASS_OF(obj) , idMethodMissing)) { raise_method_missing(th, argc+1, nargv, obj, call_status | NOEX_MISSING); } + th->passed_block = blockptr; result = rb_funcall2(obj, idMethodMissing, argc + 1, nargv); if (argv_ary) rb_ary_clear(argv_ary); return result; =end ---------------------------------------- Bug #5731: enum_for を使うと method_missing にブロックが渡されない https://bugs.ruby-lang.org/issues/5731 Author: Masahiro Tomita Status: Open Priority: Normal Assignee: Category: Target version: ruby -v: ruby 1.9.3p0 (2011-10-30) [i686-linux] 次のスクリプトを 1.9.3 で実行すると enum_for の方は block が nil になります。 1.8.7 では両方とも block が渡されました。 --------------------------------------------- class A def method_missing(name, *args, &block) p block end end a = A.new a.hoge{|l| p l} # ブロックが渡される a.enum_for(:hoge).each{|l| p l} # ブロックが渡されない --------------------------------------------- % /usr/local/ruby187/bin/ruby -v a.rb ruby 1.8.7 (2011-06-30 patchlevel 352) [i686-linux] # # % ruby -v a.rb ruby 1.9.3p0 (2011-10-30) [i686-linux] # nil # 使い方が間違ってるだけだったらすいません -- http://redmine.ruby-lang.org