我有一个包含多个方法的脚本,每个方法都有不同数量的参数:
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
是否有一种调用方法并传递所有参数的单行方式(如果没有参数则没有)?
答案 0 :(得分:2)
Ruby有一个splat运算符,一元前缀*
运算符,可以在两个具有双重含义的地方使用:
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)
......并确信不能通过危险方法