元编程:输出方法体作为文本

我在模块中动态定义一个方法,并且我想检查一旦该方法绑定到一个类实例,该方法的主体就是我所期待的。 有没有办法输出(作为文本)方法的主体?

模块controller_mixins.rb

 module ControllerMixin instance_eval "def search_by_vendor (*args) \n" \ " @#{self.class.name.sub(/Controller/, '').tableize} = #{self.class.name.sub(/Controller/, '')}.find_all_by_vendor_id(params[:vendor_id]) \n"\ "respond_to do |format| \n" \ " format.html { render :template=>'/#{self.class.name.sub(/Controller/, '').tableize}/index', :layout=>'vendor_info'} \n" \ " format.xml { render :xml => @#{self.class.name.sub(/Controller/, '').tableize} } \n" \ "end \n"\ "end \n" end 

上课与:

 class VendorOrdersController < ApplicationController # GET /vendor_orders # GET /vendor_orders.xml require 'controller_mixins' include ControllerMixin  

因此,为了方便起见,我希望看看mixin在应用于VendorOrdersController时的实现,可能是通过script/console

更新:Per @~ /我将字符串保存到变量并puts它。 这非常有效。 这揭示了我的代码中的错误(我想首先看到代码的原因)。 下面的代码要好得多,并按预期工作。

 module ControllerMixin def self.included(mod) method_body = "def search_by_vendor \n" \ " @#{mod.name.sub(/Controller/, '').tableize} = #{mod.name.sub(/Controller/, '')}.find_all_by_vendor_id(params[:vendor_id]) \n"\ "respond_to do |format| \n" \ " format.html { render :template=>'/#{mod.name.sub(/Controller/, '').tableize}/index', :layout=>'vendor_info'} \n" \ " format.xml { render :xml => @#{mod.name.sub(/Controller/, '').tableize} } \n" \ "end \n"\ "end \n" puts method_body mod.class_eval(method_body) end end 

不,你无法获得方法背后的源代码。

您可以做的最好的事情是使用Object#method获取表示方法的Method对象。 例如:

 m = VendorOrdersController.method(:search_by_vendor) 

但是你会发现只有Method#nameMethod#arityMethod#source_location等等。

但是,在您使用instance_eval之前,为什么不简单地将字符串存储在变量中,打印它?

无论如何,您的instance_eval将在模块声明时执行。 您可能希望将其包装在included回调中,以便在included时执行它。

 module ControllerMixin def self.included(mod) mod.instance_eval([...]) end end 

确保您获得预期输出的最佳方法是编写测试。

另外 – 我不赞成像这样使用instance_eval。 如果你必须使用这样的metaprogram,使用define_method ,或者你可以通过从路由传递一个参数而不做任何操作就可以逃脱,当然,这是一个更多的打字,但是那么多的元编程只是icky。

在instance_eval运行之前,是否无法将字符串分配给变量并将其输出到控制台?

由于您的字符串定义了整个方法,因此您基本上已经拥有了源代码。

如上面的答案所说,做你想做的最好的方法是使用define_method。

如果有人正在寻找“元编程:输出方法体作为文本”试试这个:

如果你想获得类或方法的代码,请查看ParseTree和ruby2ruby

ParseTree可以抓取类或方法的抽象语法树并生成“符号表达式”,如lisp,它看起来像是符号列表的列表,并且非常有趣。

ruby2ruby将这些s-exps变成普通的ruby。

请注意,ParseTree目前不适用于ruby 1.9。