How to parse rake arguments with OptionParser
Asked Answered
D

4

10

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.

Doehne answered 23/1, 2015 at 12:52 Comment(1)
is there any way to avoid using exit(0) and rake not throwing "Don't know how to build task 'foo'" when you try with rake user:create -- -u foo? what if you do not want rake to stop there? OptionParser#parse doesn't allow to use -u=foo...Buchenwald
R
8

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'

Resentment answered 23/1, 2015 at 14:42 Comment(0)
S
3

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.

Sokotra answered 23/1, 2015 at 14:13 Comment(0)
M
1

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
Macrobiotic answered 20/4, 2016 at 19:32 Comment(1)
Welcome to Stack Overflow. Please check How to Answer for tips on giving the best answers. For example, it would be helpful if you showed the most relevant code in your answer and some context for the links in case they are unavailable when future users come with similar questions.Machuca
R
-1

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

$ rake user:create -- -u=foo

Instead of:

$ rake user:create -- -u foo

Resentment answered 23/1, 2015 at 13:10 Comment(2)
With ARGV.shift it work with or without =. Unfortunately without ARGV.shift it doesn't work whenever I use = or not.Doehne
The question is how to parse general arguments in Rake, instead of how to pass arguments in rails' Rake.Leshalesher

© 2022 - 2024 — McMap. All rights reserved.