在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信息。

我们还要注意,应尽可能避免evalstring。 在你的情况下,用#class_evalreplace#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