Taskable

The Taskable module provides a generic task system patterned after Rake, but useable in any code context —not just with the Rake tool. In other words one can create methods with dependencies.

NOTE Unlike methods, tasks can’t take parameters if they are to be used as prerequisites. This capability might be added in the future, but presently syntax limitations make it awkward.

Methods
Public Instance methods
desc(line=nil)

Define description for subsequent task.

# File lib/facets/more/taskable.rb, line 150
  def desc(line=nil)
    return @last_description unless line
    @last_description = line.gsub("\n",'')
  end
desc!()

Use a description for subsequent task.

# File lib/facets/more/taskable.rb, line 157
  def desc!
    l = @last_description
    @last_description = nil
    l
  end
described_tasks()

List of task names with descriptions.

# File lib/facets/more/taskable.rb, line 179
  def described_tasks
    instance_tasks.select { |name| instance_task(name).description }
  end
instance_task( name )

Access a task.

# File lib/facets/more/taskable.rb, line 165
  def instance_task( name )
    instance_task_table[ name.to_sym ]
  end
instance_tasks()

List of task names.

# File lib/facets/more/taskable.rb, line 171
  def instance_tasks
    instance_task_table.keys
  #  t = instance_methods(true).select{ |m| m =~ /^->/ }
  #  t.collect { |e| e[2..-1].to_sym }
  end
task(args, &action)

Define a task.

# File lib/facets/more/taskable.rb, line 191
  def task(args, &action)
    if Hash === args
      raise ArgumentError, "#{args.size} for 1" if args.size != 1
      name, *deps = *(args.to_a.flatten)
      name = name.to_sym
      deps = deps.compact.collect{ |e| e.to_sym }
    else
      name, deps = args.to_sym, []
    end
    # create task via create core and callable methods.
    # We do it this way b/c otherwise we'd have to use
    # instance_eval and then can't ever pass paramaters.
    if action
      define_method( "->#{name}", &action ) # core of the task
      define_method( name ) do
        # ensure no cycles in the graph and extract call graph
        #own = (class << self; self; end) # in case there are singletons?
        todolist = Task::Graph.new( self, name )
        todolist.each_strongly_connected_component_from( name ) do |c|
          send("->#{c}")
        end
      end
      instance_task_table![name] = Task.new( name, self, deps, desc!, &action )
    elsif !instance_task_table![name]
      #define_method( "->#{name}", lambda{} )  # empty action
      define_method( name ) do
        # ensure no cycles in the graph and extract call graph
        #own = (class << self; self; end) # in case there are singletons?
        todolist = Task::Graph.new( self, name )
        todolist.each_strongly_connected_component_from( name ) do |c|
          send("->#{c}") unless "#{c}" == "#{name}"
        end
      end
      instance_task_table![name] = Task.new( name, self, deps, desc!, &action )
    else
      m = instance_task_table![name]
      #m.description = desc!  # TODO should this apply only if there is an action?
      m.prerequisite.concat deps unless deps.empty?
      m
    end
  end
undescribed_tasks()

List of task names without descriptions.

# File lib/facets/more/taskable.rb, line 185
  def undescribed_tasks
    instance_tasks.select { |name| ! instance_task(name).description }
  end