Search code examples
rubythor

How to make two thor tasks share options?


With Thor one can use method_option to set the options for a particular task. To set the options for all tasks in a class one can use class_option. But what about the case where one wants some tasks of a class, but not all, to share options?

In the following task1 and task2 shares options but they do not share all options and they share no options with task3.

require 'thor'

class Cli < Thor
  desc 'task1', 'Task 1'
  method_option :type, :type => :string, :required => true, :default => 'foo'
  def task1
  end

  desc 'task2', 'Task 2'
  method_option :type, :type => :string, :required => true, :default => 'foo'
  method_option :value, :type => :numeric
  def task2
  end

  desc 'task3', 'Task 3'
  method_option :verbose, :type => :boolean, :aliases => '-v'
  def task3
  end
end

Cli.start(ARGV)

The problem with stating method_option :type, :type => :string, :required => true, :default => 'foo' for both task1 and task2 is that it violates the DRY principle. Is there an idiomatic way of handling this?


Solution

  • method_option is defined in thor.rb and it takes the following parameters according to the documentation:

    • name<Symbol>:: The name of the argument.
    • options<Hash>:: Described below.

    Knowing this you can store the parameters to method_option in an array and expand that array into separate parameters as method_option is called.

    require 'thor'
    
    class Cli < Thor
      shared_options = [:type, {:type => :string, :required => true, :default => 'foo'}]
    
      desc 'task1', 'Task 1'
      method_option *shared_options
      def task1
      end
    
      desc 'task2', 'Task 2'
      method_option *shared_options
      method_option :value, :type => :numeric
      def task2
      end
    
      desc 'task3', 'Task 3'
      method_option :verbose, :type => :boolean, :aliases => '-v'
      def task3
      end
    end
    
    Cli.start(ARGV)
    

    I have no idea if this is idiomatic and I do not think it is that elegant. Still, it is better than violating the DRY principle.