Some time ago I was told to reimplement some Rake tasks such that they would be available from a simple admin interface. Instead of that, I came up with a web interface for Rake tasks, such that exactly the same code can be run from the web and from a console.

At the core there are a couple of global methods: runnable_tasks and run_task.

#see http://stackoverflow.com/questions/4459330/how-do-i-temporarily-redirect-stderr-in-ruby -----------------------
require "stringio"

def capture_stderr
  previous, $stderr = $stderr, StringIO.new
  yield
  $stderr.string
ensure
  $stderr = previous
end

def capture_stdout
  previous, $stdout = $stdout, StringIO.new
  yield
  $stdout.string
ensure
  $stdout = previous
end
#-------------------------------------------------------------------------------------------------------------------

# requires rake such that descriptions are collected too
def require_rake
  return if defined? Rake
  require 'rake'
  Rake::TaskManager.record_task_metadata = true
  require 'rake/testtask'
  require 'rdoc/task'
  require 'tasks/rails'
end

# returns the stdout generated by an execution of the given task
def run_task(task_name)
  require_rake
  capture_stdout { Rake.application[task_name].invoke } # or Rake::Task[task_name].invoke
end

# returns a hash (each key is a task name and each value is a task description)
def runnable_tasks(include_tasks = /.^/, exclude_tasks = /.^/) # include (and exclude) nothing for safety
  require_rake
  list = []
  tasks = Rake.application.tasks
  tasks.each do |task|
    if task.name.match(include_tasks) && ! task.name.match(exclude_tasks)
      list.push(task.name)
    end
  end
  list.sort
  result = {}
  list.each do |item|
    result[item] = Rake::Task[item].comment
  end
  result
end

And here is how that it’s supposed to be used:

result = run_task(task_name) if runnable_tasks.has_key?(task_name)