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

Soo*_*uNe 12 ruby metaprogramming

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

模块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
Run Code Online (Sandbox Code Playgroud)

上课与:

class VendorOrdersController < ApplicationController
  # GET /vendor_orders
  # GET /vendor_orders.xml
  require 'controller_mixins'
  include ControllerMixin
 <rest of class>
Run Code Online (Sandbox Code Playgroud)

因此VendorOrdersController ,script/console为了方便起见,我希望看到mixin的实现.

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

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
Run Code Online (Sandbox Code Playgroud)

Sté*_*hen 5

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

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

m = VendorOrdersController.method(:search_by_vendor)
Run Code Online (Sandbox Code Playgroud)

但是你会发现,有没有比一个更Method#name,Method#arity,Method#source_location,等.

但是,在你的情况下,为什么不简单地将字符串存储在变量中,打印它,然后再使用instance_eval

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

module ControllerMixin
  def self.included(mod)
    mod.instance_eval([...])
  end
end
Run Code Online (Sandbox Code Playgroud)