Как разобрать аргументы рейка с помощью OptionParser

Reffering answer > Я пытался использовать 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

Вы можете использовать метод 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'

Ответ 2

Я знаю, что это строго не отвечает на ваш вопрос, но рассмотрели ли вы использование аргументов задачи?

Это освободит вас от игры OptionParser и ARGV:

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.

Ответ 3

<script src="https://gist.github.com/altherlex/bb67f17cb8eefb281866fc21dfeb921a.js"></script>

Ответ 4

Вы должны поставить '=' между -u и foo:

$ rake user:create -- -u=foo

Вместо:

$ rake user:create -- -u foo