Rake 中处理#invoke 和#execute 传递的参数的统一方式

问题描述

我希望 Task 以相同的方式获取参数,对调用方法 #invoke#execute 透明:

desc "Add task"
task :add do |t,args|
  puts args.class
  puts "Add"
end

desc "Sub task"
task :sub do |t,args|
  puts args.class
  puts "Sub"
end

desc "all"
task :all do
  Rake::Task['add'].execute("arg1") # cannot set multiple arguments,will fail with "wrong number of arguments"
  Rake::Task['sub'].invoke("arg1","arg2")
end

结果是:

» rake all
String
Add
Rake::TaskArguments
Sub

检查 Rake 源代码后,很明显这些实现是不同的。

是否有一种统一的方式来管理争论,而不管它们来自哪里? (命令行,#invoke 或 #execution?)。我使用 OptParse 作为命令行参数,所以我现在在我的代码中有两个丑陋的解决方法

解决方法

我假设在 execute 的情况下,如果参数数量 > 1 那么你想要 execute 带有一个参数是一个数组,收集所有这些参数,否则 execute 将以 nil 执行或唯一的输入参数(例如字符串)。因此,您调用 execute 的方式将与您调用 invoke 的方式相匹配,而 execute 仍然与 origin 相同。

您可以为 Rake::Task#execute 创建一个包装器(别名)并如下处理输入参数

# Rakefile
Rake::Task.alias_method :old_execute,:execute
Rake::Task.define_method("execute") do |*args|
  if args&.size > 1
    old_execute(args)
  else
    old_execute(args&.first)
  end
end

# ...

Rake::Task['add'].execute # Rake::TaskArguments
Rake::Task['add'].execute("arg1") # String
Rake::Task['add'].execute("arg1","arg2") # Array