在Ruby中,class_eval << – “end_eval”,__FILE__,__LINE__是什么意思?
我正在学习如何在模块中使用class_eval(我对class_eval有点熟悉),并在resource_controller中遇到了这个有用的类 。 在那里他们有这样的事情:
class_eval <<-"end_eval", __FILE__, __LINE__ def #{block_accessor}(*args, &block) unless args.empty? && block.nil? args.push block if block_given? @#{block_accessor} = [args].flatten end @#{block_accessor} end end_eval
__FILE__
和__LINE__
在这方面做了什么? 我知道__FILE__
引用当前文件,但整个事情到底做了什么? 真的不知道如何search:)。
__FILE__
和__LINE__
是一些dynamic常量,用于保存当前正在执行的文件和行。 在这里传递他们允许错误正确报告他们的位置。
instance_eval <<-end_eval, __FILE__, __LINE__ def foo a = 123 b = :abc a.send b end end_eval foo
当你运行这个
$ ruby foo.rb foo.rb:5:in `send': undefined method `abc' for 123:Fixnum (NoMethodError) from foo.rb:5:in `foo' from foo.rb:11
注意它说的是文件和第5行,即使这只是eval中的文本。 如果没有这些文件/行的技巧,输出将如下所示:
$ ruby foo.rb (eval):5:in `send': undefined method `abc' for 123:Fixnum (NoMethodError) from (eval):5:in `foo' from foo.rb:11
堆栈跟踪只显示(eval)
,这不是很有帮助。
<<
是一个heredoc的开始。 该行是多行string的开始。 该string被删除以创build该函数。 class_eval函数使用__FILE__和__LINE__来添加debugging信息。
我们还要注意,应尽可能避免eval
string。 在你的情况下,用#class_eval
replace#class_eval
是可能的,应该是首选的:
class_exec do define_method block_accessor do |*args, &block| unless args.empty? && block.nil? args.push block if block_given? instance_variable_set "@#{block_accessor}", [args].flatten end instance_variable_get "@#{block_accessor}" end end