doridoridoriand’s diary

主に技術的なことを書いていく予定(たぶん)

Rubyのoptparseの挙動について

もう知ってる人にとっては、当たり前じゃん何言ってるのみたいな内容かもしれませんが、私は最近知ったので。。

Rubyには optparse というコマンドライン引数を読み取るライブラリが標準でついてくる。 これを使ってよくバッチ処理とかに使うスクリプトを書いてたりする。

この前書いたコードで以下のようなオプションを書いた。

OPTIONS = {}
OptionParser.new do |opt|
  opt.on('-n', '--no-daemon') {|v| OPTIONS[:no_daemon] = v}
  opt.parse!(ARGV)
end

デーモン状態で動くほうが通常モードだったアプリケーションなので、デーモン状態でない時を明示的にしたいときにと思い、 --no-daemon とした。 当初はこの引数を以下のように使用していた。

unless OPTIONS[:no_daemon]
  # :no_daemonがfalseだったときの処理(デーモン状態で動かしたいときの処理)
end

しかしどうも期待どおりの挙動を示してくれない(常にデーモン状態になる)のでドキュメントを見た。library optparse

--[no-]...などとすることで、否定型のオプションを指定することができます。

require 'optparse'
opt = OptionParser.new

opt.on('-a', '--foo') {|v| p v }
opt.on('--[no-]bar') {|v| p v }

opt.parse!(ARGV)
p ARGV

ruby sample.rb -a foo bar --bar baz --no-bar
# => true
     true
     **false**                              # <- --no-bar の指定による。
     ["foo", "bar", "baz"]

noってつけると否定形になって、falseが返ってくるのか

いつもTrueの感覚で書いていたので普通にミスった。

つわけで当初書いたここのコードブロックは

--no-daemonオプションあり => false
--no-daemonオプションなし => nil => false

となるので、常にデーモン状態となったわけだった。

最終的に以下のように修正した。

if OPTIONS[:no_daemon].nil?
  # :no_daemonがfalseだったときの処理(デーモン状態で動かしたいときの処理)
end

こっちのほうが素直な実装だとは思う。