Tldr:我正在尝试使用public_send来调用方法,但其中一些方法也需要参数。如何检查哪些需要参数并将其作为参数添加并将它们包含在调用中
我在类这样的类中有一系列方法
class_methods = [:first, :second, :third, :fourth] ...
我定义了一个can_execute
方法来检查该类是否具有该方法,如果是,它将执行。
def can_execute (class, method_name)
if class.respond_to?(method_name.to_sym) && class.class_methods.include?(method_name.to_sym)
class.public_send(method_name)
end
end
当用户提供任何class_method
作为参数时,我可以这样称呼它们
can_execute(class, method_name)
问题是其中一些方法接受哈希作为参数,如
class.first(Value: true)
或
class.second(Id: 0, Value: "string")
但是有些人没有
class.third
我不确定如何将这些class_methods
需要的params哈希包含在内?
我可以选择通过调用method_args
来检查这些方法所需的参数,例如
class.method_args(:first)
-> [:Value]
class.method_args(:second)
=> [:Id, :Value]
class.method_args(:third)
=> []
答案 0 :(得分:5)
您需要将参数传递给can_execute
,以便将其传递给public_send
。 splat运营商是你的朋友。当用作参数时,它将使用它的名称将任意数量的参数包装到数组中。在数组上使用时,它会将数组分解为参数以传递给方法。
除此之外,class
是一个关键字。惯例是将其称为klass
,但它可以是您想要的任何内容(除了类)
考虑到这一点,我们的新方法如下所示:
def can_execute (klass, method_name, *args)
if klass.respond_to?(method_name.to_sym) && klass.class_methods.include?(method_name.to_sym)
klass.public_send(method_name, *args)
end
end
然后打电话,它可以有参数。无需先检查:
can_execute('teststring', :slice, 1, 5) # => "ests"
can_execute('teststring', :upcase) # => "TESTSTRING"
如果您有其他理由要检查参数,可以使用Method#arity
或Method#parameters
。类似这样的结果为#slice
klass.method(method_name.to_sym).arity # => -1
klass.method(method_name.to_sym).parameters # => [[:rest]]