Class: Tap::Task

Inherits:
App::Api show all
Defined in:
lib/tap/task.rb

Overview

Tasks are nodes that map to the command line. Tasks provide support for configuration, documentation, and provide helpers to build workflows.

Configuration

Tasks are configurable. By default each task will be configured as specified in the class definition. Configurations may be accessed through config, or through accessors.

class ConfiguredTask < Tap::Task
  config :one, 'one'
  config :two, 'two'
end

t = ConfiguredTask.new
t.config                     # => {:one => 'one', :two => 'two'}
t.one                        # => 'one'
t.one = 'ONE'
t.config                     # => {:one => 'ONE', :two => 'two'}

Overrides and even unspecified configurations may be provided during initialization. Unspecified configurations do not have accessors.

t = ConfiguredTask.new(:one => 'ONE', :three => 'three')
t.config                     # => {:one => 'ONE', :two => 'two', :three => 'three'}
t.respond_to?(:three)        # => false

Configurations can be validated/transformed using an optional block.

Many common blocks are pre-packaged and may be accessed through the class method ā€˜cā€™:

class ValidatingTask < Tap::Task
  # string config validated to be a string
  config :string, 'str', &c.check(String)

  # integer config; string inputs are converted using YAML
  config :integer, 1, &c.yaml(Integer)
end 

t = ValidatingTask.new
t.string = 1                 # !> ValidationError
t.integer = 1.1              # !> ValidationError

t.integer = "1"
t.integer == 1               # => true

See the Configurable documentation for more information.

Subclassing

Tasks may be subclassed normally, but be sure to call super as necessary, in particular when overriding the following methods:

class Subclass < Tap::Task
  class << self
    def inherited(child)
      super
    end
  end

  def initialize(*args)
    super
  end

  def initialize_copy(orig)
    super
  end
end

Instance Attribute Summary collapse

Attributes inherited from App::Api

#app

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from App::Api

build, help, inherited, #inspect, parse, parse!, #to_spec

Methods included from Signals

#sig, #signal, #signal?, #signals

Methods included from Signals::ModuleMethods

included

Constructor Details

#initialize(config = {}, app = Tap::App.current) ⇒ Task

Returns a new instance of Task.



99
100
101
102
103
# File 'lib/tap/task.rb', line 99

def initialize(config={}, app=Tap::App.current)
  @app = app
  @joins = []
  initialize_config(config)
end

Instance Attribute Details

#joinsObject (readonly)

An array of joins for self



91
92
93
# File 'lib/tap/task.rb', line 91

def joins
  @joins
end

Class Method Details

.parser(app) ⇒ Object



77
78
79
80
81
82
83
84
85
86
87
# File 'lib/tap/task.rb', line 77

def parser(app)
  opts = super
  
  # add option to specify a config file
  opts.on('--config FILE', 'Specifies a config file') do |config_file|
    configs = Configurable::Utils.load_file(config_file, true)
    opts.config.merge!(configs)
  end
  
  opts
end

Instance Method Details

#associationsObject

Returns the associations array: [nil, joins]



161
162
163
# File 'lib/tap/task.rb', line 161

def associations
  [nil, joins]
end

#call(input) ⇒ Object

Call splats the input to process and exists to provide subclasses a way to wrap process behavior.



107
108
109
# File 'lib/tap/task.rb', line 107

def call(input)
  process(*input)
end

#enq(*args) ⇒ Object

Enques self with an array of inputs (directly use app.enq to enque with a non-array input, or override in a subclass).



139
140
141
# File 'lib/tap/task.rb', line 139

def enq(*args)
  app.enq(self, args)
end

#exe(*args) ⇒ Object

Executes self with an array of inputs (directly use app.exe to execute with a non-array input, or override in a subclass).



145
146
147
# File 'lib/tap/task.rb', line 145

def exe(*args)
  app.exe(self, args)
end

#log(action, msg = nil, level = Logger::INFO) ⇒ Object

Logs the inputs to the application logger (via app.log)



150
151
152
# File 'lib/tap/task.rb', line 150

def log(action, msg=nil, level=Logger::INFO)
  app.log(action, msg, level) { yield }
end

#on_complete(&block) ⇒ Object

Sets the block as a join for self.



155
156
157
158
# File 'lib/tap/task.rb', line 155

def on_complete(&block) # :yields: result
  joins << block if block
  self
end

#process(*inputs) ⇒ Object

The method for processing inputs into outputs. Override this method in subclasses to provide class-specific process logic. The arguments given to enq/exe should correspond to the arguments required by process. The process return is the result passed to joins.

class TaskWithTwoInputs < Tap::Task
  def process(a, b)
    [b,a]
  end
end

results = []
app = Tap::App.new

task = TaskWithTwoInputs.new({}, app)
task.enq(1,2).enq(3,4)
task.on_complete {|result| results << result }

app.run
results                 # => [[2,1], [4,3]]

By default, process simply returns the inputs.



133
134
135
# File 'lib/tap/task.rb', line 133

def process(*inputs)
  inputs
end