Class: CompositeTask
- Inherits:
-
Object
- Object
- CompositeTask
- Defined in:
- lib/composite_task.rb,
lib/composite_task/version.rb
Overview
Simple implementation of GoF Composite pattern.
Constant Summary collapse
- VERSION =
'0.2.1'
Instance Attribute Summary collapse
-
#action ⇒ Object
readonly
Task action (ie: given block).
-
#io ⇒ Object
readonly
IO like object where to write progress to.
-
#name ⇒ Object
readonly
Task name (can be nil for top level task).
-
#sub_tasks ⇒ Object
readonly
Array of all CompositeTask instances that compose this Task.
Instance Method Summary collapse
-
#[](name) ⇒ Object
Returns the first task with action with given name.
-
#add_group(name) {|sub_task| ... } ⇒ Object
Adds a sub task without an action defined.
-
#add_sub_task(task_or_name, &action) ⇒ Object
Adds a new sub task directly, or by passing its arguments (same as #initialize).
-
#call_action(indent = 0) ⇒ Object
Execute self action only, without executing any of its sub tasks.
-
#empty? ⇒ Boolean
Returns true only if self has no actions define in itself, or in any of its sub tasks.
-
#execute(indent = 0) ⇒ Object
Execute all added sub tasks (#sub_tasks) in order, then execute itself (#call_action).
-
#has_action? ⇒ Boolean
Whether self has an action.
-
#initialize(name = nil, io = STDOUT, &action) ⇒ CompositeTask
constructor
Creates a new CompositeTask, and can be used in several fashions.
-
#leaf? ⇒ Boolean
Whether it has sub tasks.
-
#length ⇒ Object
(also: #size)
Total number tasks with action that compose this task (exclude “grouping only” tasks).
-
#tasks {|_self| ... } ⇒ Object
All tasks that self is composed (including self).
-
#tasks_with_action ⇒ Object
All tasks that self is composed of(including self), but excluding the ones what #has_action? is false.
Constructor Details
#initialize(name = nil, io = STDOUT, &action) ⇒ CompositeTask
Creates a new CompositeTask, and can be used in several fashions.
For an ananymous top level class:
task = CompositeTask.new()
For a named task:
task = CompositeTask.new("Task witohut action")
For a named task, with an action block:
task = CompositeTask.new("Task with action") do |task|
puts "Executing action for #{task.name}"
end
Once created, you can compose your task with #add_sub_task and then #execute it.
Progress reporting is done to given io. can be set to nil to disable reporting. :call-seq: initialize() initialize(nil, io=STDOUT) initialize(name, io=STDOUT) initialize(name, io=STDOUT) {|task| … }
34 35 36 37 38 39 40 41 42 |
# File 'lib/composite_task.rb', line 34 def initialize(name=nil, io=STDOUT, &action) @name = name @io = io @action = action if action && !name raise ArgumentError.new('Anonymous tasks are only allowed without a block.') end @sub_tasks = [] end |
Instance Attribute Details
#action ⇒ Object (readonly)
Task action (ie: given block). Can be nil for grouping only tasks.
11 12 13 |
# File 'lib/composite_task.rb', line 11 def action @action end |
#io ⇒ Object (readonly)
IO like object where to write progress to.
14 15 16 |
# File 'lib/composite_task.rb', line 14 def io @io end |
#name ⇒ Object (readonly)
Task name (can be nil for top level task).
5 6 7 |
# File 'lib/composite_task.rb', line 5 def name @name end |
#sub_tasks ⇒ Object (readonly)
Array of all CompositeTask instances that compose this Task
8 9 10 |
# File 'lib/composite_task.rb', line 8 def sub_tasks @sub_tasks end |
Instance Method Details
#[](name) ⇒ Object
Returns the first task with action with given name.
128 129 130 |
# File 'lib/composite_task.rb', line 128 def [] name tasks_with_action.select{|s| s.name == name}.first end |
#add_group(name) {|sub_task| ... } ⇒ Object
Adds a sub task without an action defined. Yields newly created task, so it can be used to compose the task:
task.add_group("Group of tasks") do |g|
g.add_task('task1') { puts 'from task1 inside group' }
g.add_task('task2') { puts 'from task2 inside group' }
end
61 62 63 64 65 |
# File 'lib/composite_task.rb', line 61 def add_group name # :yields: sub_task sub_tasks << ( sub_task = self.class.new(name) ) yield sub_task self end |
#add_sub_task(task_or_name, &action) ⇒ Object
Adds a new sub task directly, or by passing its arguments (same as #initialize). :call-seq: add_sub_task(task) add_sub_task(name) {|task| … }
48 49 50 51 52 53 54 |
# File 'lib/composite_task.rb', line 48 def add_sub_task(task_or_name, &action) if task_or_name.kind_of?(self.class) sub_tasks << task_or_name else sub_tasks << self.class.new(task_or_name, &action) end end |
#call_action(indent = 0) ⇒ Object
Execute self action only, without executing any of its sub tasks. :call-seq: call_action
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/composite_task.rb', line 134 def call_action indent = 0 if action write_bright "#{' ' * indent}#{name}... " begin @action.call(self) rescue write_red "[FAIL]\n" raise $! else write_green "[OK]\n" end else if leaf? raise RuntimeError.new("Leaf #{name ? "\"#{name}\" " : nil}with undefined action is not allowed.") end end end |
#empty? ⇒ Boolean
Returns true only if self has no actions define in itself, or in any of its sub tasks.
123 124 125 |
# File 'lib/composite_task.rb', line 123 def empty? tasks_with_action.count == 0 end |
#execute(indent = 0) ⇒ Object
Execute all added sub tasks (#sub_tasks) in order, then execute itself (#call_action). :call-seq: execute()
70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/composite_task.rb', line 70 def execute(indent = 0) if leaf? call_action(indent) else write_bright("#{' ' * indent}#{name}\n") if name increment = name ? 1 : 0 sub_tasks.each do |task| task.execute(indent + increment) end call_action(indent + increment) end end |
#has_action? ⇒ Boolean
Whether self has an action.
107 108 109 |
# File 'lib/composite_task.rb', line 107 def has_action? !!action end |
#leaf? ⇒ Boolean
Whether it has sub tasks.
84 85 86 |
# File 'lib/composite_task.rb', line 84 def leaf? sub_tasks.empty? end |
#length ⇒ Object Also known as: size
Total number tasks with action that compose this task (exclude “grouping only” tasks).
89 90 91 |
# File 'lib/composite_task.rb', line 89 def length sub_tasks.reduce(action ? 1 : 0) {|acc, sub_task| acc + sub_task.length} end |
#tasks {|_self| ... } ⇒ Object
All tasks that self is composed (including self). :call-seq: tasks -> Enumerator tasks {|task| … }
98 99 100 101 102 103 104 |
# File 'lib/composite_task.rb', line 98 def tasks &block return to_enum(__method__) unless block_given? yield self sub_tasks.each do |sub_task| sub_task.tasks(&block) end end |
#tasks_with_action ⇒ Object
All tasks that self is composed of(including self), but excluding the ones what #has_action? is false. :call-seq: tasks_with_action -> Enumerator tasks_with_action {|task| … }
115 116 117 118 119 120 |
# File 'lib/composite_task.rb', line 115 def tasks_with_action return to_enum(__method__) unless block_given? tasks.each do |task| yield task if task.has_action? end end |