如何在运行时动态创建实例方法? [英] How to dynamically create instance methods at runtime?

查看:87
本文介绍了如何在运行时动态创建实例方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

[红宝石1.8]

假设我有:

dummy "string" do
    puts "thing" 
end

现在,这是对一个方法的调用,该方法具有一个输入字符串和一个块作为输入参数.很好.

Now, this is a call to a method which has as input arguments one string and one block. Nice.

现在假设我可以进行很多类似的调用(不同的方法名称,相同的参数).示例:

Now assume I can have a lot of similar calls (different method names, same arguments). Example:

otherdummy "string" do
    puts "thing"
end

现在,因为它们执行相同的操作,并且可能有数百个,所以我不想为想要的类中的每个实例创建一个实例方法.我宁愿找到一种聪明的方法,根据一般规则在运行时动态定义该方法.

Now because they do the same thing, and they can be hundreds, I don't want create an instance method for each one in the wanted class. I would like rather find a smart way to define the method dynamically at runtime based on a general rule.

有可能吗?常用的技术有哪些?

Is that possible? Which techniques are commonly used?

谢谢

推荐答案

我特别喜欢使用method_missing,尤其是当您希望在各种方法调用中使用的代码非常相似时.以下是网站中的示例-每当有人调用x.booboo不存在时,都会使用booboo的参数和(可选)一个块来调用method_missing:

I'm particularly fond of using method_missing, especially when the code you want to use is very similar across the various method calls. Here's an example from this site - whenever somebody calls x.boo and boo doesn't exist, method_missing is called with boo, the arguments to boo, and (optionally) a block:

class ActiveRecord::Base
  def method_missing(meth, *args, &block)
    if meth.to_s =~ /^find_by_(.+)$/
      run_find_by_method($1, *args, &block)
    else
      super # You *must* call super if you don't handle the
            # method, otherwise you'll mess up Ruby's method
            # lookup.
    end
  end

  def run_find_by_method(attrs, *args, &block)
    # Make an array of attribute names
    attrs = attrs.split('_and_')

    # #transpose will zip the two arrays together like so:
    #   [[:a, :b, :c], [1, 2, 3]].transpose
    #   # => [[:a, 1], [:b, 2], [:c, 3]]
    attrs_with_args = [attrs, args].transpose

    # Hash[] will take the passed associative array and turn it
    # into a hash like so:
    #   Hash[[[:a, 2], [:b, 4]]] # => { :a => 2, :b => 4 }
    conditions = Hash[attrs_with_args]

    # #where and #all are new AREL goodness that will find all
    # records matching our conditions
    where(conditions).all
  end
end

define_method看起来也很适合您,但是我对它的经验少于method_missing.这是来自同一链接的示例:

define_method also looks like it would work for you, but I have less experience with it than method_missing. Here's the example from the same link:

%w(user email food).each do |meth|
  define_method(meth) { @data[meth.to_sym] }
end

这篇关于如何在运行时动态创建实例方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆