Rubyでcliを作るときに定番のgem thorではコマンドのオプション(--key value
みたいなやつ)を定義するときにmethod_option
を利用する.
しかし,いくつかのブログやドキュメント等を参照すると他にもいくつかの方法がある.
この違いがよくわからなかったのでいろいろ確認した.
オプション定義方法を解説する2種類のドキュメント
thorのドキュメントとしては,GitHub wikiと公式webサイトの2種類存在する.
GitHub wikiでは method_option
と method_options
で定義する方法が紹介されている.
こちらのwikiには option
/ options
を用いて定義する方法については触れられていない.
Thor allows you to specify options for its tasks, using method_options to supply a hash of options, or method_option to provide more detail about an individual option.
method_option :value, :default => "some value"
#=> Creates a string option with a default value of "some value"
一方で,公式webサイトでは Options and Flags
の章にて option
と options
を用いて定義する方法が紹介されている.
こちらのドキュメントには method_option
/ method_options
を用いて定義する方法については触れられていない.
Thor makes it easy to specify options and flags as metadata about a Thor command:
class MyCLI < Thor
desc "hello NAME", "say hello to NAME"
option :from
def hello(name)
puts "from: #{options[:from]}" if options[:from]
puts "Hello #{name}"
end
end
なお method_options
と method_option
の違いについて GitHub wiki には,
method_option
は個別のオプションに対してより詳細な項目を定義するために利用すると説明がある.
options
と option
の違いについて公式webサイトには,
options
は複数の option
を一度に定義できると説明がある.
上記の説明では, method_option
と method_options
の関係は options
と option
の関係とは異なるように読める.
You can use a shorthand to specify a number of options at once if you just want to specify the type of the options.
また,公式webサイトには上記に加えて Class Options
の章で class_option
という別の方法が記載されている.
class_option
はGitHub wikiでは説明はなく,Generators と Groupsで参照されているだけだった.
ただし,公式webサイトでは触れられていない class_options
も参照されている.
You can specify an option that should exist for the entire class by using class_option. Class options take exactly the same parameters as options for individual commands, but apply across all commands for a class.
class MyCLI < Thor
class_option :verbose, :type => :boolean
desc "hello NAME", "say hello to NAME"
options :from => :required, :yell => :boolean
def hello(name)
puts "> saying hello" if options[:verbose]
output = []
output << "from: #{options[:from]}" if options[:from]
output << "Hello #{name}"
output = output.join("\n")
puts options[:yell] ? output.upcase : output
puts "> done saying hello" if options[:verbose]
end
desc "goodbye", "say goodbye to the world"
def goodbye
puts "> saying goodbye" if options[:verbose]
puts "Goodbye World"
puts "> done saying goodbye" if options[:verbose]
end
end
使い分け
method_options と options
この疑問についてはまさに同じ内容のissueが報告されている.
参考: Difference between method_options and options #596
結論としてはどちらも同じ.GitHub wikiは内容が古くなっているということ.
実際,GitHub wikiには内容が古くなっているので公式wbサイトを参照してくれと注意書きがある
NOTE: a good part of the documentation here is outdated, see the website instead: http://whatisthor.com
実装を見ても, method_optionsで実装されて options でエイリアスが張られている.
同様に, method_option で実装されて optionでエイリアスが張られてもいる.
alias_method :options, :method_options
alias_method :option, :method_option
method_options と method_option
一方で, method_options
と method_option
(および options
と option
)の違いについて,
単に method_options
は複数の method_option
を同時に指定できるというだけでなく,
method_option
でしか定義できない詳細オプションがある様子.
すなわち GitHub wikiが正しい (公式webサイトの記載を自分が読み違えている?).
具体的には,method_options
では :required
, :type
, :default
, :aliases
の4つしか指定できない.
これはmethod_options
を指定したときの処理の実装上,この4つしか対応していないように読める.
その他の指定可能な項目として,公式webサイトでは :desc
, :banner
を,
GitHub wikiでは上記に加えて :lazy_default
, :enum
を,
オプション項目の生成処理の実装を見ると上記に加えて :hide
を
それぞれ指定可能のように見える.
method_options と class_options
class_options
および class_option
は説明の通り,指定したクラスに定義されたコマンドすべてに適用される.
利用可能な項目は method_options
および method_option
と等しい.
なお,class_option実装のコメントを見ると lazy_default
の記載がない.
しかし実際には class_option
も method_option
も共通の build_optionで生成しているので
おそらく laze_default
も含めて共通化されている.
結論
-
method_options
とoptions
,method_option
とoption
の機能はそれぞれ同じ.どちらを利用してもよい. -
method_options
とmethod_option
は役割が異なる.-
method_options
は異なる複数のオプションに対して,method_option
は単一のオプションに対して項目を指定する. -
method_options
はrequired
,type
,default
,aliases
の計4項目を指定できる. -
method_option
では上記に加えてdesc
,banner
,lazy_default
,enum
,hide
の計9項目を指定できる.
-
-
method_options
とclass_options
は対象となるコマンドが違うだけで同じ項目を指定できる.class_option
も同様. - ドキュメントは GitHub wikiと公式webサイトがあるが,どちらも古いので両方とも鵜呑みにできない.