在Rake Task中使用OptionParser的正确调用方法咨询
问题:嵌套命名空间Rake任务的选项调用报错
我编写了一个带嵌套命名空间的Rake任务,通过OptionParser定义了-v/--verbose选项,但调用时出现各种错误:
- 使用
bin/rails a:b:c -v 3或bin/rails a:b:c -- -v 3时,报错“Unrecognized command '3'” - 使用
bundle exec rake a:b:c -- -v 3时,输出options: {}且提示找不到任务'3'
任务代码
require "optparse" namespace :a do namespace :b do task c: :environment do options = {} OptionParser.new do |parser| parser.banner = "" parser.on("-v", "--verbose", "Run verbosely") do |v| options[:verbose] = v end end.parse! puts "options: #{options}" end end end
调用报错信息
使用bin/rails调用时
Unrecognized command "3" (Rails::Command::UnrecognizedCommandError)
使用bundle exec rake调用时
a@mac appa % bundle exec rake a:b:c -- -v 3 options: {} rake aborted! Don't know how to build task '3' (See the list of available tasks with `rake --tasks`) /Users/sa/.rbenv/versions/3.3.7/bin/bundle:25:in `load' /Users/sa/.rbenv/versions/3.3.7/bin/bundle:25:in `<main>' (See full trace by running task with --trace)
正确调用方式与问题原因
问题根源
- 当前代码里的
-v/--verbose是无参数的开关选项,但你调用时传了3,这个值会被Rake/Rails当成额外的任务名,导致报错。 - Rails命令会优先解析自身选项,必须用
--明确分隔任务和自定义选项;Rake在无歧义时可以直接传选项,但如果选项带参数,也需要--分隔。
正确调用方式
情况1:保持开关型verbose(不需要参数)
- Rake调用:
或者用bundle exec rake a:b:c -v--分隔(更稳妥):bundle exec rake a:b:c -- -v - Rails调用(必须用
--分隔):bin/rails a:b:c -- -v
情况2:需要给verbose传递参数(比如等级3)
先修改OptionParser的定义,让选项接受参数:
require "optparse" namespace :a do namespace :b do task c: :environment do options = {} OptionParser.new do |parser| parser.banner = "" # 修改这里,指定选项接受LEVEL参数 parser.on("-v", "--verbose LEVEL", "Run verbosely with level") do |level| options[:verbose] = level.to_i end end.parse! puts "options: #{options}" end end end
然后调用:
- Rake:
bundle exec rake a:b:c -- -v 3 - Rails:
bin/rails a:b:c -- -v 3
内容的提问来源于stack exchange,提问作者Sig
相关产品推荐
相关产品推荐

