Skip to content
geniousli edited this page Jul 18, 2017 · 9 revisions

Thor has a special class called Thor::Group. All of the tasks defined in a Thor::Group are invoked together as a sequence, in the order that they were defined. The example from Invocations could be rewritten using Thor::Group as: myawesomegem/lib/mycounter_file.rb

require 'thor/group'

module MyAwesomeGem
  class MyCounter < Thor::Group
    desc "Prints 1 2 3"

    def one
      puts 1
    end

    def two
      puts 2
    end

    def three
      puts 3
    end
  end
end

When invoked:

thor my_awesome_gem:my_counter
# prints "1 2 3"

Note that in order to add the Thor::Group subclass to the commands list of your executable, you have to register it first.
Building on the executables explanation found in Making An Executable, let's say that you have a file:
myawesomegem/bin/command

#!/usr/bin/env ruby
require File.expand_path('lib/command', Dir.pwd)
MyAwesomeGem::MyCommand.start

And then, the file containing the actual command:
myawesomegem/lib/command.rb

require "thor"
module MyAwesomeGem
  class MyCommand < Thor
    desc "foo", "Prints foo"
    def foo
      puts "foo"
    end
  end
end
MyAwesomeGem::MyCommand.start

Test executable file:

cd myawesomegem
chmod a+x bin/command # make permission
bin/command foo

To make MyCounter available as a subcommand, you need to call the register method:
myawesomegem/lib/command.rb

require "thor"
require File.expand_path("lib/mycounter_file", Dir.pwd)
module MyAwesomeGem
  class MyCommand < Thor
    desc "foo", "Prints foo"
    def foo
      puts "foo"
    end
    
    # register(class_name, subcommand_alias, usage_list_string, description_string)
    register(MyAwesomeGem::MyCounter, "counter", "counter", "Prints some numbers in sequence")
  end
end

Now the class MyCounter < Thor::Group will appear as a sub-task within mycommand with the alias counter, usage:

bin/command
# Commands:
#  command counter         # Prints numbers in sequence
#  command foo             # Prints foo

bin/command counter
#=> 1 2 3

Note: when using Thor::Group, the description you provide (using the method desc) is for the entire class, as opposed to providing a description for each task.

Also, Thor::Group can parse arguments and options as Thor tasks:

class Counter < Thor::Group
  # number will be available as attr_accessor
  argument :number, :type => :numeric, :desc => "The number to start counting"
  desc "Prints the 'number' given upto 'number+2'"

  def one
    puts number + 0
  end

  def two
    puts number + 1
  end

  def three
    puts number + 2
  end
end

The counter above expects one parameter and has the following outputs:

thor counter 5
# Prints "5 6 7"

thor counter 11
# Prints "11 12 13"

You can also give options to Thor::Group, but instead of using method_option and method_options, you should use class_option and class_options. Both argument and class_options methods are available to Thor class as well.

Thor::Group is a great tool to create generators, since you can define several steps which are invoked in the order they are defined (Thor::Group is the tool used for generators in Rails 4.x).

Clone this wiki locally