How to Make Two Thor Tasks Share Options

How to make two thor tasks share options?

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.

Mutually exclusive options with Thor

I haven't found a built-in way to do this, but you could accomplish it with your own simple check. Here's an example Thor command that does what you want.

desc "command", "A command that does something."
option :list, aliases: 'l', type: :array
option :file, aliases: 'f'
def list
if options[:list] && options[:file]
puts "Use only one, --list(-l) or --file(-f)"
exit(0)
end
# Place the functions of the command here
end

Hope this helps!

How to call a Thor task multiple times?

Looking through the Thor docs I couldn't find a way to force invokation of the same task multiple times. This is probably by design.

I've created a workaround that will do what you ask by combining the report generation requests into a single task which in turn relies on a the "no_task" block Thor makes available for non-task methods. You have the flexibility to add new reports to be generated by adding them to the hash argument passed to generate.

class MisReport < Thor

desc "all", "generate mysql and postgres mis"
def all
generate({:pg_mis_report => "pg", :mysql_mis_report => "mysql"})
end

desc "generate", "generate mis report"
def generate(hash)
hash.each_pair {|file_name, connection| generate_report(file_name.to_s, connection)}
end

no_tasks{
def generate_report(file_name = "mis_report_#{Time.now.to_s(:number)}", connection = "postgres")

if connection == "pg"
puts "== postgres database"
#ActiveRecord::Base.establish_connection :development_mysql
else
puts "== mysql database"
#ActiveRecord::Base.establish_connection :development
end

# generate MIS

file_path = "/some/path/to/#{file_name}"
puts
puts "mis file is at: #{file_path}"
end
}

end

I've tested it and output is shown here:

$> thor mis_report:all
== postgres database

mis file is at: /some/path/to/pg_mis_report
== mysql database

mis file is at: /some/path/to/mysql_mis_report

Hope this helps.



Related Topics



Leave a reply



Submit