如何使用OptionParser解析rake参数

10

参考那篇回答,我试图使用OptionParser解析rake参数。我从中简化了示例,并不得不添加两个ARGV.shift才能使其正常工作。

require 'optparse'

namespace :user do |args|

  # Fix I hate to have here
  puts "ARGV: #{ARGV}"
  ARGV.shift
  ARGV.shift
  puts "ARGV: #{ARGV}"

  desc 'Creates user account with given credentials: rake user:create'
  # environment is required to have access to Rails models
  task :create => :environment do
    options = {}
    OptionParser.new(args) do |opts|      
      opts.banner = "Usage: rake user:create [options]"
      opts.on("-u", "--user {username}","Username") { |user| options[:user] = user }
    end.parse!

    puts "user: #{options[:user]}"

    exit 0
  end
end

以下是输出结果:

$ rake user:create -- -u foo
ARGV: ["user:create", "--", "-u", "foo"]
ARGV: ["-u", "foo"]
user: foo

我认为ARGV.shift不是正确的方法。我想知道为什么没有它就无法正常工作,以及如何以正确的方式修复它。


1
有没有办法避免使用exit(0),并且在使用rake user:create -- -u foo时,rake不会抛出“Don't know how to build task 'foo'”?如果您不想让rake在那里停止怎么办? OptionParser#parse不允许使用-u = foo... - rellampec
4个回答

8
您可以使用方法OptionParser#order!,该方法返回没有错误参数的ARGV:
options = {}

o = OptionParser.new

o.banner = "Usage: rake user:create [options]"
o.on("-u NAME", "--user NAME") { |username|
  options[:user] = username
}
args = o.order!(ARGV) {}
o.parse!(args)
puts "user: #{options[:user]}"

你可以像这样传递参数:$ rake foo:bar -- '--user=john'

3
我知道这并没有直接回答你的问题,但是你考虑过使用任务参数吗?
这样可以避免你需要操作OptionParserARGV
namespace :user do |args|
  desc 'Creates user account with given credentials: rake user:create'
  task :create, [:username] => :environment do |t, args|
    # when called with rake user:create[foo],
    # args is now {username: 'foo'} and you can access it with args[:username]
  end
end

更多信息请参见此处SO的答案


1

试试这个:

require 'optparse'

namespace :programs do |args|
  desc "Download whatever"
  task :download => [:environment] do

    # USAGE: rake programs:download -- rm
    #-- Setting options $ rake programs:download -- --rm
    options = {}
    option_parser = OptionParser.new
    option_parser.banner = "Usage: rake programs:download -- rm"
    option_parser.on("-r", "--rm","Remove s3 files downloaded") do |value|
      options[:remove] = value
    end
    args = option_parser.order!(ARGV) {}
    option_parser.parse!(args)
    #-- end

    # your code here
  end
end

1
欢迎来到 Stack Overflow。请查看 [答案] 以获取有关提供最佳答案的提示。例如,如果您在答案中显示了最相关的代码和一些上下文信息,那么当未来用户遇到类似问题时,这将非常有帮助。 - Kateract

-1

-ufoo之间必须加上'=':

$ rake user:create -- -u=foo

而不是:

$ rake user:create -- -u foo


使用 ARGV.shift 可以在有或没有 = 的情况下正常工作。不幸的是,如果没有 ARGV.shift,无论我是否使用 =,它都无法正常工作。 - pawel7318
1
问题是如何在Rake中解析一般的参数,而不是如何在Rails的Rake中传递参数。 - Xiao Hanyu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接