Ruby: 需要子类文件时如何捕获并解析未定义的方法
Ruby: How to capture and resolve undefined method when requiring a subclass file
有一个我需要解析的 DSL ruby 文件。看起来像
# file B.rb
class B < A
hello "John"
end
hello "Mary"
它在 class B
.
的内部和外部调用带有字符串参数的函数 hello()
我尝试 require
文件 B.rb
并解决缺少的方法:
# file A.rb
# define a class A for subclassing, before loading B.rb
class A
end
# Try to catch the missing methods
def method_missing(name, *args, &block)
puts "tried to handle unknown method %s" % name # name is a symbol
end
require("./B.rb")
在 运行 这段代码之后,method_missing
导致无限循环。
如何捕获和解析class B
内部和外部未定义的方法?我想知道在DSL文件中调用了哪些方法和参数。
我在评论中暗示了这种方法,但认为拼写出来可能会有用。
所以首先我们需要在某些东西上定义 method_missing
,我们不能在顶层定义它,因为我们会收到这个警告
redefining Object#method_missing may cause infinite loop
相反,我们将在 class A
上定义它(在 class 级别)。
# in a.rb
class A
def self.method_missing(name, *args, &block)
puts "tried to handle unknown method %s" % name # name is a symbol
end
end
现在我们可以使用 class_eval
在 class A
的范围内计算 b.rb
像这样:
# also in a.rb
A.class_eval(File.read("./b.rb"))
现在“顶级”hello "Mary"
调用实际上在 A
的 class 范围内执行(method_missing
定义处于活动状态)。此外,由于 class B
继承自 A
,它在 class 级别上也有 method_missing
定义,因此 hello "John"
调用也会命中它。
所以 运行 脚本,我看到 tried to handle unknown method hello
打印了两次,正如预期的那样。
我应该指出,我不认为以这种方式“忽略”错误是个好主意……很可能最好停止程序的执行。但也许你有什么需要它的想法,我不能确定。
你的这一行 method_missing
,
puts "tried to handle unknown method %s" % name # name is a symbol
调用未定义的 to_ary
并最终再次调用 method_missing
。因此你的无限循环。
def method_missing(name, *args, &block)
p name
puts "tried to handle unknown method %s" % name # name is a symbol
end
# =>
...
...
:to_ary
:to_ary
:to_ary
/System/Library/.../kernel_require.rb:55: stack level too deep (SystemStackError)
如果您想以这种方式进行修复,则修复非常简单。使用字符串插值。
puts "tried to handle unknown method #{name.to_s}"
# =>
Tried to handle unknown method hello
Tried to handle unknown method hello
有一个我需要解析的 DSL ruby 文件。看起来像
# file B.rb
class B < A
hello "John"
end
hello "Mary"
它在 class B
.
hello()
我尝试 require
文件 B.rb
并解决缺少的方法:
# file A.rb
# define a class A for subclassing, before loading B.rb
class A
end
# Try to catch the missing methods
def method_missing(name, *args, &block)
puts "tried to handle unknown method %s" % name # name is a symbol
end
require("./B.rb")
在 运行 这段代码之后,method_missing
导致无限循环。
如何捕获和解析class B
内部和外部未定义的方法?我想知道在DSL文件中调用了哪些方法和参数。
我在评论中暗示了这种方法,但认为拼写出来可能会有用。
所以首先我们需要在某些东西上定义 method_missing
,我们不能在顶层定义它,因为我们会收到这个警告
redefining Object#method_missing may cause infinite loop
相反,我们将在 class A
上定义它(在 class 级别)。
# in a.rb
class A
def self.method_missing(name, *args, &block)
puts "tried to handle unknown method %s" % name # name is a symbol
end
end
现在我们可以使用 class_eval
在 class A
的范围内计算 b.rb
像这样:
# also in a.rb
A.class_eval(File.read("./b.rb"))
现在“顶级”hello "Mary"
调用实际上在 A
的 class 范围内执行(method_missing
定义处于活动状态)。此外,由于 class B
继承自 A
,它在 class 级别上也有 method_missing
定义,因此 hello "John"
调用也会命中它。
所以 运行 脚本,我看到 tried to handle unknown method hello
打印了两次,正如预期的那样。
我应该指出,我不认为以这种方式“忽略”错误是个好主意……很可能最好停止程序的执行。但也许你有什么需要它的想法,我不能确定。
你的这一行 method_missing
,
puts "tried to handle unknown method %s" % name # name is a symbol
调用未定义的 to_ary
并最终再次调用 method_missing
。因此你的无限循环。
def method_missing(name, *args, &block)
p name
puts "tried to handle unknown method %s" % name # name is a symbol
end
# =>
...
...
:to_ary
:to_ary
:to_ary
/System/Library/.../kernel_require.rb:55: stack level too deep (SystemStackError)
如果您想以这种方式进行修复,则修复非常简单。使用字符串插值。
puts "tried to handle unknown method #{name.to_s}"
# =>
Tried to handle unknown method hello
Tried to handle unknown method hello