传递多个参数发送

时间:2017-05-05 12:47:19

标签: ruby

我有一个包含多个方法的脚本,每个方法都有不同数量的参数:

def method1

end

def method2(arg1)

end

def method3(arg1, arg2)

end

def method4(arg1, arg2, arg3)

end

我需要从命令行调用这些方法,我目前正在这样做:

if ARGV.length == 1
  send(ARGV[0])
elsif ARGV.length == 2
  send(ARGV[0], ARGV[1])
else
  send(ARGV[0], ARGV[1], ARGV[2])
end

是否有一种调用方法并传递所有参数的单行方式(如果没有参数则没有)?

3 个答案:

答案 0 :(得分:2)

Ruby有一个splat运算符,一元前缀*运算符,可以在两个具有双重含义的地方使用:

  • 在方法,块或lambda定义中的参数列表中,它意味着"将所有剩余的参数打包成Array并将其绑定到此参数"
  • 在消息发送的参数列表yield以及赋值表达式的左侧,它表示"爆炸此{{1}将它们分成各个元素,好像它们已经单独写在了它的位置"

所以,例如:

Array

相当于

foo(*some_array)

因此,在您的情况下,您需要做的就是

foo(some_array[0], some_array[1], some_array[2], …, some_array[some_array.size])

请注意,这显然允许任何可以操纵send(*ARGV) 的人执行任何任意Ruby代码,包括但不限于擦除硬盘或启动众所周知的核导弹。但是,您的原始代码具有相同的缺陷。你真的应该在这里进行验证,但这与你的问题是正交的。

答案 1 :(得分:0)

你可以用这个:

send("method#{ARGV.size+1}", *ARGV)

举个例子:

def method1
  puts "METHOD 1. No parameter"
end

def method2(arg1)
  puts "METHOD 2. #{arg1}"
end

def method3(arg1, arg2)
  puts "METHOD 3. #{arg1}, #{arg2}"
end

def method4(arg1, arg2, arg3)
  puts "METHOD 4. #{arg1}, #{arg2}, #{arg3}"
end

args = %w(a b c)

send("method#{args.size+1}", *args)
# METHOD 4. a, b, c
但是,它不是很干净或健壮。

您可以使用splat运算符(*args)进行方法定义和调用:

def generic_method(*args)
  puts "Generic method has been called with #{args.size} parameters: #{args.inspect}"
  # Add logic here
end

generic_method
# Generic method has been called with 0 parameters: []
generic_method('a')
# Generic method has been called with 1 parameters: ["a"]
generic_method('a', 'b', 'c')
# Generic method has been called with 3 parameters: ["a", "b", "c"]

不再需要send

答案 2 :(得分:0)

正如Ursus建议的那样(但现在他的答案已经消失)你可以用

来做到这一点
send(*ARGV)

但这有潜在危险,因为这适用于ARGV[0]中的任何方法,所以你应该有一些机制来确保只允许某些方法

filter_send(*ARGV)

def filter_send(method, *arguments)
  send(method, *arguments) if good_method?(method)
end

def good_method?(sent_method)
  %w(method1 method2 method3 method4).include?(sent_method.to_s)
end

所以现在你可以做...

filter_send(*ARGV)

......并确信不能通过危险方法