[Ruby] 6 ways to define options in thor

4 minute read

When creating a cli with Ruby, the standard gem thorusesmethod_optionwhendefiningcommandoptions(suchas--keyvalue). Use. However, if you refer to some blogs and documents, there are some other methods. I didn’t understand this difference well, so I checked various things.

Two types of documents explaining how to define options

There are two types of thor documents: GitHub wikiandofficialwebsite.

The Method defined by method_option and method_options is introduced on the GitHub wiki. This wiki does not mention how to define using 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.

Sample of

GitHub/wiki


method_option :value, :default => "some value"
#=> Creates a string option with a default value of "some value"

On the other hand, on the official website, the method of defining with option and options is introduced in the chapter of Options and Flags. This document does not mention how to define using method_option / method_options.

Thor makes it easy to specify options and flags as metadata about a Thor command:

sample on official website


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

Note that the difference between method_options and method_option is on the GitHub wiki, It is explained that method_option can be used to define more detailed items for individual options. The official website about the difference between options and option is It is explained that options can define multiple options at once. In the above explanation, the relationship between method_option and method_options can be read differently from the relationship between options and 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.

In addition to the above, another method called class_option is described in the chapter Class Options on the official website. class_option is not explained on the GitHub wiki, and is Generatorsand[Groups](https://github.com/erikhuda/thor/wiki/Itwasonlyreferencedin(Groups). However, class_options, which is not mentioned on the official website, is also referenced.

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_option sample on official website


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

proper use

method_options and options

The exact same issue has been reported for this question. Reference: Difference between method_options and options #596

The conclusion is that both are the same. The GitHub wiki is out of date. In fact, the GitHub wiki has a note that the content is outdated, so please refer to the official wb site

NOTE: a good part of the documentation here is outdated, see the website instead: http://whatisthor.com

Even if you look at the implementation, it is implemented with method_options and [aliased] with options (https://github.com/erikhuda/thor/blob/34df888d721ecaa8cf0cea97d51dc6c388002742/lib/thor.rb#L128). Similarly, it is implemented by method_option and is [aliased] by option (https://github.com/erikhuda/thor/blob/34df888d721ecaa8cf0cea97d51dc6c388002742/lib/thor.rb#L165).

lib/thor.rb#128


alias_method :options, :method_options

lib/thor.rb#165


alias_method :option, :method_option

method_options and method_option

On the other hand, about the difference between method_options and method_option (and options and option), Not only can method_options specify more than one method_option at the same time, It looks like there are advanced options that can only be defined with method_option. In other words, the GitHub wiki is correct (I am reading the official website incorrectly?).

Specifically, method_options can specify only four: :required, :type, :default, and :aliases. This is due to the implementation of the process when method_options is specified only supports these four. Other items that can be specified are :desc and :banner on the official website. In GitHub wiki, in addition to the above, :lazy_default, :enum, Looking at Implementation of option item generation processing, in addition to the above, add :hide It seems that each can be specified.

method_options and class_options

class_options and class_option apply to all commands defined in the specified class, as described. The available items are equivalent to method_options and method_option.

If you look at Comment on implementing class_option, there is no description of lazy_default. However, in reality, both class_option and method_option are generated by the common build_option. Probably it is common, including laze_default.

Conclusion* The functions of method_options and options, method_option and option are the same. Either may be used.

  • method_options and method_option have different roles.
    • method_options specifies items for different options, and method_option specifies items for a single option.
    • method_options can specify 4 items in total: required, type, default, and aliases.
    • In addition to the above, method_option can specify a total of 9 items including desc, banner, lazy_default, enum, and hide.
  • method_options and class_options can specify the same item except that the target commands are different. The same applies to class_option.
  • The documentation is available on the GitHub wiki and the official website, but both are old and cannot be swallowed.