不能在顶层对象中定义 method_missing。

当我尝试在pry中定义(通过加载脚本&只是在pry中输入)method_missing时,它只是退出到控制台(windows xp上的cmd)。当我试着在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 

这是我的代码。

def method_missing name, *args, &block
  puts 'method is missing'
  nil
end

some_missing_method("lol")

当我返回其他东西时,它没有进入无限循环,而是显示错误(只有前几行在改变)。Number:

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'
        (..)

解决方案:

所以这需要对Ruby的类对象模块层次结构有一定的了解,也需要对IRB和Pry等工具的工作原理有一定的了解。看看这个,它可能会让你大吃一惊,就像我的一样——。https:/web.archive.orgweb20160319051340http:/madebydna.comallcode20110624eigenclasses-demystified.html。.

至于IRB和Pry,我对他们的代码了解不多,但我知道他们基本上是通过读取你的输入和eval’ing+大量的魔法来工作的。

你似乎已经知道了,当你在irbpry中时,你是在 Object 范围,几乎所有其他的东西都是从这个范围继承的。包括IRB和Pry本身. 所以,覆盖的东西在 Object譬如 method_missing的行为,可能会改变所有从它派生出来的东西(即Everything)的行为,包括IRBPry。Pry可能会覆盖 method_missing 本身要做一些非常重要的事情,而你的改变就是打破了这一点。

你可以把这个作为一个有趣的实验来尝试。

def method_missing name, *args, &block
  puts "method '#{name}' is missing"
end

这可能会给你 一些 不知道为什么会这样,但简短的回答是… … 不要这样做. 将你的代码封装到自己的模块中,这样就不会干扰到其他任何东西。

我可能把自己搞糊涂了,但是这个 可能 让事情重新运转起来。它应该能恢复普莱对你的任何期望 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 #”的错误。这或多或少地恢复了 pryirb 期待的行为:即 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 在某个循环中。所以如果它从来没有被提起过,循环就会一直持续下去。如果是这样,那么上面的方法应该可以解决这个问题。并不是说我推荐这样做。

给TA打赏
共{{data.count}}人
人已打赏
未分类

如何在flutter中获取用户的城市位置?

2022-9-19 13:01:39

未分类

在不阻止当前执行的情况下,从c程序中启动和停止一个linux shell命令[已解决]。

2022-9-19 13:01:41

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索