当我尝试定义(通过加载脚本和只是输入pry)method_missing in pry时它只是退出到控制台(cmd on windows xp)。
当我尝试在IRB上键入它时,它会进入无限循环或当我尝试加载脚本时(irb m.rb)它会显示如下内容:
D:\programowanie\Ruby>irb m.rb
m.rb(main):001:0> def method_missing name, *args, &block
m.rb(main):002:1> puts 'method is missing'
m.rb(main):003:1> end
=> nil
m.rb(main):004:0>
m.rb(main):005:0* some_missing_method("lol")method is missing
m.rb(main):005:0*
method is missing
method is missing
method is missing
m.rb(main):005:0>
method is missing
method is missing
method is missing
method is missing
然后它退出到控制台(cmd)
这是我的代码:
def method_missing name, *args, &block
puts 'method is missing'
nil
end
some_missing_method("lol")
当我返回其他内容时,它不会进入无限循环但显示错误(仅前几行正在改变):
号:
method is missing
method is missing
C:/RailsInstaller/Ruby1.9.3/lib/ruby/site_ruby/1.9.1/readline.rb:45:in `raise': can't convert TypeError to String (TypeError#to_str gives Fixnum) (Typ
eError)
from C:/RailsInstaller/Ruby1.9.3/lib/ruby/site_ruby/1.9.1/readline.rb:45:in `rescue in readline'
from C:/RailsInstaller/Ruby1.9.3/lib/ruby/site_ruby/1.9.1/readline.rb:39:in `readline'
from C:/RailsInstaller/Ruby1.9.3/lib/ruby/1.9.1/irb/input-method.rb:115:in `gets'
from C:/RailsInstaller/Ruby1.9.3/lib/ruby/1.9.1/irb.rb:139:in `block (2 levels) in eval_input'
from C:/RailsInstaller/Ruby1.9.3/lib/ruby/1.9.1/irb.rb:273:in `signal_status'
from C:/RailsInstaller/Ruby1.9.3/lib/ruby/1.9.1/irb.rb:138:in `block in eval_input'
from C:/RailsInstaller/Ruby1.9.3/lib/ruby/1.9.1/irb/ruby-lex.rb:188:in `call'
from C:/RailsInstaller/Ruby1.9.3/lib/ruby/1.9.1/irb/ruby-lex.rb:188:in `buf_input'
from C:/RailsInstaller/Ruby1.9.3/lib/ruby/1.9.1/irb/ruby-lex.rb:103:in `getc'
from C:/RailsInstaller/Ruby1.9.3/lib/ruby/1.9.1/irb/slex.rb:205:in `match_io'
from C:/RailsInstaller/Ruby1.9.3/lib/ruby/1.9.1/irb/slex.rb:75:in `match'
from C:/RailsInstaller/Ruby1.9.3/lib/ruby/1.9.1/irb/ruby-lex.rb:286:in `token'
from C:/RailsInstaller/Ruby1.9.3/lib/ruby/1.9.1/irb/ruby-lex.rb:262:in `lex'
from C:/RailsInstaller/Ruby1.9.3/lib/ruby/1.9.1/irb/ruby-lex.rb:233:in `block (2 levels) in each_top_level_statement'
from C:/RailsInstaller/Ruby1.9.3/lib/ruby/1.9.1/irb/ruby-lex.rb:229:in `loop'
from C:/RailsInstaller/Ruby1.9.3/lib/ruby/1.9.1/irb/ruby-lex.rb:229:in `block in each_top_level_statement'
from C:/RailsInstaller/Ruby1.9.3/lib/ruby/1.9.1/irb/ruby-lex.rb:228:in `catch'
from C:/RailsInstaller/Ruby1.9.3/lib/ruby/1.9.1/irb/ruby-lex.rb:228:in `each_top_level_statement'
from C:/RailsInstaller/Ruby1.9.3/lib/ruby/1.9.1/irb.rb:155:in `eval_input'
from C:/RailsInstaller/Ruby1.9.3/lib/ruby/1.9.1/irb.rb:70:in `block in start'
from C:/RailsInstaller/Ruby1.9.3/lib/ruby/1.9.1/irb.rb:69:in `catch'
from C:/RailsInstaller/Ruby1.9.3/lib/ruby/1.9.1/irb.rb:69:in `start'
from C:/RailsInstaller/Ruby1.9.3/bin/irb:12:in `<main>'
字符串:
method is missing
method is missing
C:/RailsInstaller/Ruby1.9.3/lib/ruby/site_ruby/1.9.1/readline.rb:45:in `rescue in readline': this_is_string (RuntimeError)
from C:/RailsInstaller/Ruby1.9.3/lib/ruby/site_ruby/1.9.1/readline.rb:39:in `readline'
(..)
答案 0 :(得分:2)
因此,这需要对Ruby的类/对象/模块层次结构有所了解,以及对IRB和Pry等工具的工作方式有所了解。看看这个,这可能会像我一样打击你的思绪 - http://madebydna.com/all/code/2011/06/24/eigenclasses-demystified.html。
至于IRB和Pry,我对他们的代码知之甚少,但我知道他们基本上是通过阅读你的输入和评估+大量的魔法来工作。
正如你似乎已经知道的那样,当你处于irb / pry时,你就在Object
范围内,几乎所有其他东西都继承,包括IRB和Pry自己 。所以覆盖Object
中的某些内容,如method_missing
,可能会改变从它下降的所有内容(即Everything)的行为,包括IRB / Pry。 Pry可能会覆盖method_missing
本身做一些非常重要的事情,而你的改变正在打破这一点。
你可以尝试这个有趣的实验:
def method_missing name, *args, &block
puts "method '#{name}' is missing"
end
这可能会让你一些想法为什么会这样,但简短的回答是不要这样做。将您的代码封装到自己的模块中,这样它就不会干扰其他任何内容。
我可能会在这里混淆自己,但这个可能让事情再次发挥作用。它应该恢复Pry对Object#method_missing
的所有期望:
def method_missing name, *args, &block
puts "method '#{name}' is missing"
super
end
修改强>
是的,我认为BasicObject#method_missing
不存在。但是没关系,因为上面的super
会引发一个错误,例如“NoMethodError:undefined method missing_method'for#”。这或多或少会恢复pry / irb似乎期待的行为:Object#method_missing
应最终提升NoMethodError
。这应该可以修复无限递归循环。
然而,更好的解决方案(除了首先不覆盖Object#method_missing
)可能是在做了你必须做的其他事情之后自己筹集NoMethodError
:
def method_missing(name, *args, &block)
puts "method '#{name}' is missing"
# important stuff
raise NoMethodError, name
end
我的猜测是,pry正在某个循环中从NoMethodError
中抢救。因此,如果它永远不会被提升,那么循环将永远持续下去。如果这是对的,那么上面应该解决它。不是我推荐它。