pawel7318
pawel7318

Reputation: 3583

How to parse rake arguments with OptionParser

Reffering that answer I was trying to use OptionParser to parse rake arguments. I simplified example from there and I had to add two ARGV.shift to make it work.

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

This is the output:

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

I assume ARGV.shift is not the way it should be done. I would like to know why it doesn't work without it and how to fix it in a proper way.

Upvotes: 10

Views: 5913

Answers (4)

Alther Alves
Alther Alves

Reputation: 11

Try this:

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

Upvotes: 1

rubycademy.com
rubycademy.com

Reputation: 529

You can use the method OptionParser#order! which returns ARGV without the wrong arguments:

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]}"

You can pass args like that: $ rake foo:bar -- '--user=john'

Upvotes: 8

awendt
awendt

Reputation: 13663

I know this does not strictly answer your question, but did you consider using task arguments?

That would free you having to fiddle with OptionParser and 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

For more info, see this answer here on SO.

Upvotes: 3

rubycademy.com
rubycademy.com

Reputation: 529

You have to put a '=' between -u and foo:

$ rake user:create -- -u=foo

Instead of:

$ rake user:create -- -u foo

Upvotes: -1

Related Questions