Class: Rap::Task
- Inherits:
-
Tap::Task
- Object
- Tap::Task
- Rap::Task
- Extended by:
- Declarations
- Defined in:
- lib/rap/task.rb,
lib/rap/declarations.rb
Overview
Rap tasks are a special breed of Tap::Task designed to behave much like Rake tasks. As such, declaration tasks:
-
return nil and pass nil in workflows
-
only execute once
-
are effectively singletons (one instance per app)
-
allow for multiple actions
The Rap::Task class partially includes Declarations so subclasses may directly declare tasks. A few alias acrobatics makes it so that ONLY Declarations#task is made available (desc cannot be used because Task classes already use that method for documentation, and namespace would be silly).
Weird? Yes, but it leads to this syntax:
# [Rapfile]
# class Subclass < Rap::Task
# def helper(); "help"; end
# end
#
# # ::desc a help task
# Subclass.task(:help) {|task, args| puts "got #{task.helper}"}
% rap help
got help
Class Attribute Summary collapse
-
.actions ⇒ Object
An array of actions (blocks) associated with this class.
-
.arg_names ⇒ Object
The argument names pulled from a task declaration.
Instance Attribute Summary collapse
-
#args ⇒ Object
The arguments assigned to self during call.
-
#result ⇒ Object
readonly
The result of self, set by call.
Class Method Summary collapse
-
.args ⇒ Object
Returns a Lazydoc::Arguments constructed from arg_names.
-
.instantiate(argh = {}, app = Tap::App.instance) ⇒ Object
Instantiates the instance of self for app and reconfigures it as specified in argh.
-
.parse!(argv = ARGV, app = Tap::App.instance) ⇒ Object
Parses as normal, but also stores the arguments on the instance to allows arguments to be specified on dependency tasks:.
-
.subclass(const_name, configs = {}, dependencies = []) ⇒ Object
Looks up or creates the Rap::Task subclass specified by const_name and adds the configs and dependencies.
Instance Method Summary collapse
-
#call(*args) ⇒ Object
Conditional call to the super call; only calls once.
-
#initialize(config = {}, app = Tap::App.instance) ⇒ Task
constructor
A new instance of Task.
-
#process(*inputs) ⇒ Object
Collects the inputs into an OpenStruct according to the class arg_names, and calls each class action in turn.
-
#reset ⇒ Object
Resets self so call will call again.
-
#resolved? ⇒ Boolean
Returns true if already resolved by call.
Methods included from Declarations
app, app=, current_desc, current_namespace, desc, env, env=, instance, namespace, task
Methods included from Utils
Constructor Details
#initialize(config = {}, app = Tap::App.instance) ⇒ Task
Returns a new instance of Task.
146 147 148 149 150 151 |
# File 'lib/rap/task.rb', line 146 def initialize(config={}, app=Tap::App.instance) super @resolved = false @result = nil @args = nil end |
Class Attribute Details
.actions ⇒ Object
An array of actions (blocks) associated with this class. Each of the actions is called during process, with the instance and any args passed to process organized into an OpenStruct.
44 45 46 |
# File 'lib/rap/task.rb', line 44 def actions @actions ||= [] end |
.arg_names ⇒ Object
The argument names pulled from a task declaration.
52 53 54 |
# File 'lib/rap/task.rb', line 52 def arg_names @arg_names ||= [] end |
Instance Attribute Details
#args ⇒ Object
The arguments assigned to self during call.
144 145 146 |
# File 'lib/rap/task.rb', line 144 def args @args end |
#result ⇒ Object (readonly)
The result of self, set by call.
141 142 143 |
# File 'lib/rap/task.rb', line 141 def result @result end |
Class Method Details
.args ⇒ Object
Returns a Lazydoc::Arguments constructed from arg_names.
57 58 59 60 61 |
# File 'lib/rap/task.rb', line 57 def args args = Lazydoc::Arguments.new arg_names.each {|name| args.arguments << name.to_s } args end |
.instantiate(argh = {}, app = Tap::App.instance) ⇒ Object
Instantiates the instance of self for app and reconfigures it as specified in argh.
82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/rap/task.rb', line 82 def instantiate(argh={}, app=Tap::App.instance) instance = self.instance(app) if config = argh[:config] instance.reconfigure(config) end if args = argh[:args] instance.args = args end instance end |
.parse!(argv = ARGV, app = Tap::App.instance) ⇒ Object
Parses as normal, but also stores the arguments on the instance to allows arguments to be specified on dependency tasks:
# [Rapfile]
# Rap.task(:a, :obj) {|t, a| puts "A #{a.obj}"}
# Rap.task({:b => :a}, :obj) {|t, a| puts "B #{a.obj}"}
% rap b world -- a hello
A hello
B world
74 75 76 77 78 |
# File 'lib/rap/task.rb', line 74 def parse!(argv=ARGV, app=Tap::App.instance) instance = super instance.args = argv instance end |
.subclass(const_name, configs = {}, dependencies = []) ⇒ Object
Looks up or creates the Rap::Task subclass specified by const_name and adds the configs and dependencies.
Configurations are always validated using the yaml transformation block (see Configurable::Validation).
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/rap/task.rb', line 101 def subclass(const_name, configs={}, dependencies=[]) # lookup or generate the subclass subclass = Tap::Env::Constant.constantize(const_name.to_s) do |base, constants| subclass_const = constants.pop constants.inject(base) do |namespace, const| # nesting Task classes into other Task classes is required # for namespaces with the same name as a task namespace.const_set(const, Class.new(Rap::Task)) end.const_set(subclass_const, Class.new(self)) end # check a correct class was found unless subclass.ancestors.include?(self) raise "not a #{self}: #{subclass}" end # append configuration (note that specifying a desc # prevents lazydoc registration of these lines) convert_to_yaml = Configurable::Validation.yaml configs.each_pair do |key, value| subclass.send(:config, key, value, :desc => "", &convert_to_yaml) end # add dependencies dependencies.each do |dependency| dependency_name = File.basename(dependency.to_s.underscore) # this suppresses 'method redefined' warnings if subclass.method_defined?(dependency_name) subclass.send(:undef_method, dependency_name) end subclass.send(:depends_on, dependency_name, dependency) end subclass end |
Instance Method Details
#call(*args) ⇒ Object
Conditional call to the super call; only calls once. Returns result.
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/rap/task.rb', line 154 def call(*args) # Declaration tasks function as dependencies, but unlike normal # dependencies, they CAN take arguments from the command line. # Such arguments will be set as args, and be used to enque the # task. # # If the task executes from the queue first, args will be # provided to call and they should equal self.args. If the task # executes as a dependency first, call will not receive args and # in that case self.args will be used. # # This warns for cases that odd workflows can produce where the # args have been set and DIFFERENT args are used to enque the task. # In these cases always go with the pre-set args but warn the issue. self.args ||= args unless self.args == args if @resolved warn "warn: ignorning dependency task inputs #{args.inspect} (#{self})" else warn "warn: invoking dependency task with preset args #{self.args.inspect} and not inputs #{args.inspect} (#{self})" end end unless @resolved @resolved = true @result = super(*self.args) end result end |
#process(*inputs) ⇒ Object
Collects the inputs into an OpenStruct according to the class arg_names, and calls each class action in turn. This behavior echoes the behavior of Rake tasks.
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
# File 'lib/rap/task.rb', line 199 def process(*inputs) # collect inputs to make a rakish-args object args = {} self.class.arg_names.each do |arg_name| break if inputs.empty? args[arg_name] = inputs.shift end args = OpenStruct.new(args) # execute each block assciated with this task self.class.actions.each do |action| case action.arity when 0 then action.call() when 1 then action.call(self) else action.call(self, args) end end nil end |
#reset ⇒ Object
Resets self so call will call again. Also sets result to nil.
191 192 193 194 |
# File 'lib/rap/task.rb', line 191 def reset @resolved = false @result = nil end |
#resolved? ⇒ Boolean
Returns true if already resolved by call.
186 187 188 |
# File 'lib/rap/task.rb', line 186 def resolved? @resolved end |