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)
不,你无法获得方法背后的源代码.
您可以做的最好的事情是获取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)