是否可以在Ruby中定义带有可选参数的块?

时间:2009-01-16 19:45:48

标签: ruby

我正在尝试动态定义调用另一个带有options参数的函数的函数:

class MyClass
  ["hour", "minute", "second"].each do |interval|
    define_method "get_#{interval}" do |args|
      some_helper(interval, args)
    end
  end
  def some_helper(interval, options={})
    # Do something, with arguments
  end
end

我希望能够以这两种方式调用MyClass上的不同方法(使用和不使用可选参数):

mc = MyClass.new
mc.get_minute( :first_option => "foo", :second_option => "bar")
mc.get_minute  # This fails with: warning: multiple values for a block parameter (0 for 1)

在第二次打电话时,我看到了这个警告:

  

警告:块参数的多个值(0表示1)

  1. 有没有办法为“get_ *”方法编写块,以便不会出现此警告?
  2. 我是否滥用了define_method?

3 个答案:

答案 0 :(得分:16)

您需要做的唯一更改是将args更改为*args*表示args将包含块的可选参数数组。

答案 1 :(得分:5)

两年后...... 我不知道是否是ruby 1.9.2的新功能,或者过去是否也可以使用,但这有效:

class MyClass
    ["hour", "minute", "second"].each do |interval|
        define_method "get_#{interval}" do |args = {:first_option => "default foo", :second_option => "default  bar"}|
           some_helper(interval, args)
        end
    end
    def some_helper(interval, options={})
        # Do something, with arguments
        p options
    end
end

mc = MyClass.new
mc.get_minute( :first_option => "foo", :second_option => "bar")
mc.get_minute  

结果是:

{:first_option=>"foo", :second_option=>"bar"}
{:first_option=>"default foo", :second_option=>"default  bar"}

答案 2 :(得分:0)

我同意戈登在你的args中添加*会让它消失。

另一种方法是使用method_missing()

这样的事情:

class MyClass

  def method_missing(m, *args)  
    if /get_(.+)/.match(m.to_s)
      some_helper($1, args) 
    else
      raise 'Method not found...'
    end
  end  

  def some_helper(interval, *args)
    puts interval + ' -> ' + args.inspect
  end

end

m = MyClass.new
m.get_minute( :first_option => "foo", :second_option => "bar" )