page 248, top of page, code using OptionParser. If I put traces in Rakefile :
puts "*** in Rakefile #{Time.now.strftime('%H:%M:%S')} ***"
def delete(dir, pattern)
puts "in delete dir=#{dir}, pattern=#{pattern}"
files = Dir["#{dir}/#{pattern}"]
rm(files, verbose: true) unless files.empty?
end
desc "Remove files whose names end with a tilde"
task :delete_unix_backups do
dir = "."
puts 'before new'
parser = OptionParser.new
puts 'before on'
parser.on("-d") { |opt| dir = opt }
puts 'before parse!'
parser.parse!
delete(dir, "*~")
end
and execute rake without parameter, it loads the Rakefile :
% rake delete_unix_backups
*** in Rakefile 19:02:18 ***
before new
before on
before parse!
in delete dir=., pattern=*~
But with an invalid parameter, it doesn’t even load the Rakefile :
% rake delete_unix_backups -x
invalid option: -x
Despite the fact that the documentation rake/command_line_usage.rdoc at master · ruby/rake · GitHub puts [options ...]
before [targets ...]
, obviously rake takes the options for him, as with --dry-run (-n) :
% rake delete_unix_backups -n
*** in Rakefile 19:03:07 ***
** Invoke delete_unix_backups (first_time)
** Execute (dry run) delete_unix_backups
Paragraph after the code :
Then you’d call this with rake delete_unix_backups -d code The parse! command removes the
options from ARGV, preventing Rake from considering them as their own tasks.
Unfortunately it’s impossible to pass -d to OptionParser in task :delete_unix_backups
:
% rake --trace delete_unix_backups -d del
rake aborted!
OptionParser::AmbiguousOption: ambiguous option: -d
/Users/b/.rvm/gems/ruby-3.0.0/gems/rake-13.0.6/lib/rake/application.rb:659:in `handle_options'
/Users/b/.rvm/gems/ruby-3.0.0/gems/rake-13.0.6/lib/rake/application.rb:92:in `block in init'
/Users/b/.rvm/gems/ruby-3.0.0/gems/rake-13.0.6/lib/rake/application.rb:186:in `standard_exception_handling'
/Users/b/.rvm/gems/ruby-3.0.0/gems/rake-13.0.6/lib/rake/application.rb:89:in `init'
/Users/b/.rvm/gems/ruby-3.0.0/gems/rake-13.0.6/lib/rake/application.rb:81:in `block in run'
/Users/b/.rvm/gems/ruby-3.0.0/gems/rake-13.0.6/lib/rake/application.rb:186:in `standard_exception_handling'
/Users/b/.rvm/gems/ruby-3.0.0/gems/rake-13.0.6/lib/rake/application.rb:80:in `run'
/Users/b/.rvm/gems/ruby-3.0.0/gems/rake-13.0.6/exe/rake:27:in `<top (required)>'
/Users/b/.rbenv/versions/3.2.0/bin/rake:25:in `load'
/Users/b/.rbenv/versions/3.2.0/bin/rake:25:in `<main>'
Caused by:
OptionParser::InvalidOption: invalid option: d
Did you mean? D
...
The reason is handle_options
in rake’s application.rb
92 :
87 # Initialize the command line parameters and app name.
88 def init(app_name="rake", argv = ARGV)
89 standard_exception_handling do
90 @name = app_name
91 begin
92 args = handle_options argv
93 rescue ArgumentError
94 # Backward compatibility for capistrano
95 args = handle_options
96 end
97 collect_command_line_tasks(args)
98 end
99 end
641 # Read and handle the command line options. Returns the command line
642 # arguments that we didn't understand, which should (in theory) be just
643 # task names and env vars.
644 def handle_options(argv) # :nodoc:
645 set_default_options
646
647 OptionParser.new do |opts||
...
657 standard_rake_options.each { |args| opts.on(*args) }
658 opts.environment("RAKEOPT")
659 end.parse(argv)
660 end
which parses the options before you have a chance to add a new one in the task.