我有很多这样的方法:
def create_machine(name, os_type_id, settings_file='', groups=[], flags={})
soap_method = "#{self.class.name.split('::').last.to_underscore}_#{__method__}".to_sym
args = method(__method__).parameters.map { |arg| arg[1] }
soap_message = Hash[args.map { |arg| [arg, eval(arg.to_s)] }]
VirtualBoxAPI.send_request(@cl.conn, soap_method, @this.merge(soap_message))
end
def register_machine(machine)
soap_method = "#{self.class.name.split('::').last.to_underscore}_#{__method__}".to_sym
args = method(__method__).parameters.map { |arg| arg[1] }
soap_message = Hash[args.map { |arg| [arg, eval(arg.to_s)] }]
VirtualBoxAPI.send_request(@cl.conn, soap_method, @this.merge(soap_message))
end
它们具有相同的实现,但不同数量的不同参数。在数十个类中的每一个中都会有数十个这样的方法。所以我想我会使用一些元编程来最小化代码重复。我试图通过这样做,define_method
并希望以这样的方式结束:
vb_method :create_machine, :args => [:name, :os_type_id], :optional_args => [:settings_file, :groups, :flags]
但是我找不到将任意数量的命名(非 splat)参数传递给define_method
的方法(我认为 splat 参数会使记录方法变得难以甚至不可能,也会使生成的 API 不方便)。
处理这个问题的最佳方法是什么(使用 Ruby 2.0)?
UPD 另一种方法是定义一个方法 vb_method:
def vb_method(*vb_meths)
vb_meths.each do |meth|
define_method(meth) do |message={}|
soap_method = "#{self.class.name.split('::').last.to_underscore}_#{meth}".to_sym
VirtualBoxAPI.send_request(@cl.conn, soap_method, @this.merge(message))
end
end
end
然后班级会有这样的电话:
vb_method :create_machine, :register_machine
但在这种情况下,我将需要始终以 hash 作为参数调用方法:
machine = vb.create_machine(name: 'my_vm', os_type_id: 'Windows95')
这正是我要避免的,因为我认为在这种情况下,生成的 API 无法记录并且使用起来不方便。