如何在不使用哈希的情况下向方法发送任意数量的参数?

时间:2013-01-25 18:08:04

标签: ruby http refactoring

我正在使用Curb,一个围绕cURL的红宝石包装。

我想首先说我知道方法缺失等方法可以接受任意数字args和块,如果这样定义:

def method_missing(meth, *args, &block); ... end

*args是一组参数。

现在,我正在尝试重构我对HTTP GET,POST等方法的调用,通过使用Curb执行以下操作:

req = Curl::Easy.send("http_#{method.to_s}", *args) do |curl| ... end

其中args可以是1个参数或2个参数,我试图定义如下:

args = [url]
args << data if data

但是当我调用Curl::Easy.send行时出现错误。

both block arg and actual block given

以下是我尝试访问的方法的一些示例(https://github.com/taf2/curb/blob/master/lib/curl/easy.rb):

      def http_get(*args)
        c = Curl::Easy.new *args
        yield c if block_given?
        c.http_get
        c
      end 

      def http_put(url, data)
        c = Curl::Easy.new url
        yield c if block_given?
        c.http_put data
        c
      end

      def http_post(*args)
        url = args.shift
        c = Curl::Easy.new url
        yield c if block_given?
        c.http_post *args
        c
      end

      def http_delete(*args)
        c = Curl::Easy.new *args
        yield c if block_given?
        c.http_delete
        c
      end

所有这些都被设置为接受任意数量的参数,除了put。 但是,实际上,对于http_get,我只需要传递一个URL(在URL中使用查询参数)。所以,我只想为http_get传递一个参数,为其他传递2个参数。

1 个答案:

答案 0 :(得分:0)

如果我理解正确,您希望根据方法的参数数量发送x个参数。以下内容将根据给出的数据起作用。

method_name = "http_#{method.to_s}"
params = Curl::Easy.method(:"#{method_name}").parameters
req = Curl::Easy.send("http_#{method.to_s}", *(args[0..(params.size-1)])) do |curl| ... end```

然而,您提出的错误是当您发送Proc作为参数并传递一个块时,它会按照您的要求执行,但如果没有堆栈跟踪来缩小范围,我不会认为这会解决你的错误。即

irb(main):001:0> def tst(&block)
irb(main):002:1> end
=> nil
irb(main):003:0> arg = Proc.new { }
=> #<Proc:0x00000002cd6930@(irb):3>
irb(main):004:0> tst(&arg) do
irb(main):005:1* end
SyntaxError: (irb):5: both block arg and actual block given

作为旁注,#parameters返回类似[[:rest][:args]]的内容,并且:rest表示其余参数,因此您可以随时对参数进行更多检查以提供更精细的参数。