带有参数的Ruby DSL define_method

时间:2013-11-12 20:09:36

标签: ruby dsl

这就是我要做的事。

# DSL Commands
command :foo, :name, :age
command :bar, :name

# Defines methods
def foo(name, age)
  # Do something
end

def bar(name)
  # Do something
end

基本上,我需要一种通过define_method处理参数的方法,但我想要一个定义数量的参数而不是一个arg数组(即*args

这是我到目前为止所拥有的

def command(method, *args)
  define_method(method) do |*args|
    # Do something
  end
end

# Which would produce
def foo(*args)
  # Do something
end

def bar(*args)
  # Do something
end

思想?

2 个答案:

答案 0 :(得分:3)

我认为最好的解决方法是做以下事情:

def command(method, *names)
  count = names.length
  define_method(method) do |*args|

    raise ArgumentError.new(
      "wrong number of arguments (#{args.length} for #{count})"
    ) unless args.length == count

    # Do something
  end
end

答案 1 :(得分:3)

这有点奇怪,但您可以使用某种类型的evalinstance_evalmodule_evalclass_eval可用于此目的,具体取决于具体情况。这样的事情:

def command(method, *args)
  instance_eval <<-EOS, __FILE__, __LINE__ + 1
    def #{method}(#{args.join(', ')})
      # method body
    end
  EOS
end

这样,您将获得每种方法的确切参数数量。是的,它可能比“一点点”更奇怪。