Search code examples
rubyrakethor

How to call a Thor task multiple times?


Thor like Rake (and Make) has task management. If I call a task multiple times, it will effectively call the task only once. How can I call a task multiple times?

I tried modifying the @_invocations hash, but that did not work:

require 'csv'
require './config/environment'

class MisReport < Thor

  desc "all", "generate mysql and postgres mis"
  def all
    generate("pg_mis_report", "pg")
    generate("mysql_mis_report", "mysql") 
  end

  desc "generate", "generate mis report"
  def generate(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

    puts
    puts "mis file is at: #{file_path}"
  end

end

Solution

  • 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.