模块中的动态方法?

时间:2010-08-02 18:32:40

标签: ruby dynamic module methods

我有一个名为AB的模块。现在它看起来像这样:

module AB
    extend self

    def some_method(hash)
        ....
    end

    ....
end

我们像这样使用它:AB.some_method(:thing =>:what,:etc =>'你得到了主意')。用户必须传递大约六个字符串,我想变成动态方法,而不是AB.some_method(:thing =>:无论......)他们只是打电话给AB .whatever(...)或AB :: what(...)。我以为我可以用method_missing做到这一点,但我想我不明白。我做了这样的事情:

module AB
    def method_missing(name,*args)
        super unless THINGS.include?(name.to_s)
        ...
    end
end

但是在尝试调用AB :: what时我从未涉及过该方法。我想过使用define_method循环使用THINGS,但我不确定如何定义带参数的方法。

任何帮助表示感谢。

2 个答案:

答案 0 :(得分:4)

第二个代码示例中的问题是method_missing应该声明为self.method_missing。以下按预期工作:

module AB
  THINGS = %w(whatever)

  def self.method_missing(name, *args)
    super unless THINGS.include?(name.to_s)
    "responding to #{name}"
  end
end

p AB.whatever    #=> "responding to whatever"
p AB.something   #=> NoMethodError

答案 1 :(得分:0)

我认为您可以使用两种不同的方法,一种是动态定义方法,另一种是依赖method_missing。以下是两者的示例:

# first approach, define methods
class MyClassDefine
  def some_method args
    p args
  end

  [:foo,:bar].each do |name|
    define_method name do |args|
      # assume args is a hash, fix me
      some_method args.merge({:thing => name})
    end
  end
end

# second approach, use method_missing
class MyClassMissing
    def some_method args
    p args
  end

  def method_missing name, args
    super unless [:foo, :bar].include? name
    # again, assuming argument is a hash
    some_method args.merge(:thing => name)
  end
end

mcd = MyClassDefine.new
mcd.foo :etc => 'you get idea'
#=> {:etc=>"you get idea", :thing=>:foo}

mcm = MyClassMissing.new
mcm.foo :etc => 'you get idea'
#=> {:etc=>"you get idea", :thing=>:foo}

这里剩下的工作是覆盖方法传递方法而不是哈希的情况作为参数。