Class: TrakFlow::Models::Task
- Inherits:
-
Object
- Object
- TrakFlow::Models::Task
- Defined in:
- lib/trak_flow/models/task.rb
Overview
Represents a task in the TrakFlow system
Tasks serve multiple roles determined by flags:
-
Plan (blueprint): task.plan? == true
-
Workflow: task.source_plan_id.present? && !task.plan?
-
Step (conceptual): child Task of a Plan
-
Work item: child Task of a Workflow
Tasks can be bugs, features, tasks, epics, or chores
Constant Summary collapse
- VALID_STATUSES =
TrakFlow::STATUSES
- VALID_PRIORITIES =
TrakFlow::PRIORITIES
- VALID_TYPES =
TrakFlow::TYPES
Instance Attribute Summary collapse
-
#assignee ⇒ Object
Returns the value of attribute assignee.
-
#closed_at ⇒ Object
Returns the value of attribute closed_at.
-
#content_hash ⇒ Object
Returns the value of attribute content_hash.
-
#created_at ⇒ Object
Returns the value of attribute created_at.
-
#description ⇒ Object
Returns the value of attribute description.
-
#ephemeral ⇒ Object
Returns the value of attribute ephemeral.
-
#id ⇒ Object
Returns the value of attribute id.
-
#notes ⇒ Object
Returns the value of attribute notes.
-
#parent_id ⇒ Object
Returns the value of attribute parent_id.
-
#plan ⇒ Object
Returns the value of attribute plan.
-
#priority ⇒ Object
Returns the value of attribute priority.
-
#source_plan_id ⇒ Object
Returns the value of attribute source_plan_id.
-
#status ⇒ Object
Returns the value of attribute status.
-
#title ⇒ Object
Returns the value of attribute title.
-
#type ⇒ Object
Returns the value of attribute type.
-
#updated_at ⇒ Object
Returns the value of attribute updated_at.
Class Method Summary collapse
Instance Method Summary collapse
- #append_trace(action, message) ⇒ Object
- #blocked? ⇒ Boolean
- #close!(reason: nil) ⇒ Object
- #closed? ⇒ Boolean
- #discardable? ⇒ Boolean
- #ephemeral? ⇒ Boolean
- #epic? ⇒ Boolean
- #errors ⇒ Object
- #executable? ⇒ Boolean
- #in_progress? ⇒ Boolean
-
#initialize(attrs = {}) ⇒ Task
constructor
A new instance of Task.
- #open? ⇒ Boolean
-
#plan? ⇒ Boolean
Plan/Workflow role predicates.
- #reopen!(reason: nil) ⇒ Object
- #to_h ⇒ Object
- #to_json(*args) ⇒ Object
- #touch! ⇒ Object
- #update_content_hash! ⇒ Object
- #valid? ⇒ Boolean
- #validate! ⇒ Object
- #workflow? ⇒ Boolean
Constructor Details
#initialize(attrs = {}) ⇒ Task
Returns a new instance of Task.
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/trak_flow/models/task.rb', line 23 def initialize(attrs = {}) @id = attrs[:id] @title = attrs[:title] @description = attrs[:description] || "" @status = attrs[:status] || "open" @priority = attrs[:priority] || 2 @type = attrs[:type] || "task" @assignee = attrs[:assignee] @parent_id = attrs[:parent_id] @created_at = attrs[:created_at] || Time.now.utc @updated_at = attrs[:updated_at] || Time.now.utc @closed_at = attrs[:closed_at] @content_hash = attrs[:content_hash] @plan = attrs[:plan] || false @source_plan_id = attrs[:source_plan_id] @ephemeral = attrs[:ephemeral] || false @notes = attrs[:notes] || "" end |
Instance Attribute Details
#assignee ⇒ Object
Returns the value of attribute assignee.
15 16 17 |
# File 'lib/trak_flow/models/task.rb', line 15 def assignee @assignee end |
#closed_at ⇒ Object
Returns the value of attribute closed_at.
15 16 17 |
# File 'lib/trak_flow/models/task.rb', line 15 def closed_at @closed_at end |
#content_hash ⇒ Object
Returns the value of attribute content_hash.
15 16 17 |
# File 'lib/trak_flow/models/task.rb', line 15 def content_hash @content_hash end |
#created_at ⇒ Object
Returns the value of attribute created_at.
15 16 17 |
# File 'lib/trak_flow/models/task.rb', line 15 def created_at @created_at end |
#description ⇒ Object
Returns the value of attribute description.
15 16 17 |
# File 'lib/trak_flow/models/task.rb', line 15 def description @description end |
#ephemeral ⇒ Object
Returns the value of attribute ephemeral.
15 16 17 |
# File 'lib/trak_flow/models/task.rb', line 15 def ephemeral @ephemeral end |
#id ⇒ Object
Returns the value of attribute id.
15 16 17 |
# File 'lib/trak_flow/models/task.rb', line 15 def id @id end |
#notes ⇒ Object
Returns the value of attribute notes.
15 16 17 |
# File 'lib/trak_flow/models/task.rb', line 15 def notes @notes end |
#parent_id ⇒ Object
Returns the value of attribute parent_id.
15 16 17 |
# File 'lib/trak_flow/models/task.rb', line 15 def parent_id @parent_id end |
#plan ⇒ Object
Returns the value of attribute plan.
15 16 17 |
# File 'lib/trak_flow/models/task.rb', line 15 def plan @plan end |
#priority ⇒ Object
Returns the value of attribute priority.
15 16 17 |
# File 'lib/trak_flow/models/task.rb', line 15 def priority @priority end |
#source_plan_id ⇒ Object
Returns the value of attribute source_plan_id.
15 16 17 |
# File 'lib/trak_flow/models/task.rb', line 15 def source_plan_id @source_plan_id end |
#status ⇒ Object
Returns the value of attribute status.
15 16 17 |
# File 'lib/trak_flow/models/task.rb', line 15 def status @status end |
#title ⇒ Object
Returns the value of attribute title.
15 16 17 |
# File 'lib/trak_flow/models/task.rb', line 15 def title @title end |
#type ⇒ Object
Returns the value of attribute type.
15 16 17 |
# File 'lib/trak_flow/models/task.rb', line 15 def type @type end |
#updated_at ⇒ Object
Returns the value of attribute updated_at.
15 16 17 |
# File 'lib/trak_flow/models/task.rb', line 15 def updated_at @updated_at end |
Class Method Details
.from_hash(hash) ⇒ Object
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/trak_flow/models/task.rb', line 160 def from_hash(hash) hash = hash.transform_keys(&:to_sym) new( id: hash[:id], title: hash[:title], description: hash[:description], status: hash[:status], priority: hash[:priority]&.to_i, type: hash[:type], assignee: hash[:assignee], parent_id: hash[:parent_id], created_at: TimeParser.parse(hash[:created_at]), updated_at: TimeParser.parse(hash[:updated_at]), closed_at: TimeParser.parse(hash[:closed_at]), content_hash: hash[:content_hash], plan: hash[:plan], source_plan_id: hash[:source_plan_id], ephemeral: hash[:ephemeral], notes: hash[:notes] ) end |
.from_json(json_string) ⇒ Object
182 183 184 |
# File 'lib/trak_flow/models/task.rb', line 182 def from_json(json_string) from_hash(Oj.load(json_string, mode: :compat, symbol_keys: true)) end |
Instance Method Details
#append_trace(action, message) ⇒ Object
123 124 125 126 127 128 |
# File 'lib/trak_flow/models/task.rb', line 123 def append_trace(action, ) = Time.now.utc.iso8601 entry = "[#{}] [#{action}] #{}" self.notes = "#{notes}\n#{entry}".strip touch! end |
#blocked? ⇒ Boolean
74 75 76 |
# File 'lib/trak_flow/models/task.rb', line 74 def blocked? status == "blocked" end |
#close!(reason: nil) ⇒ Object
104 105 106 107 108 109 |
# File 'lib/trak_flow/models/task.rb', line 104 def close!(reason: nil) self.status = "closed" self.closed_at = Time.now.utc self.notes = "#{notes}\n[Closed] #{reason}".strip if reason touch! end |
#closed? ⇒ Boolean
66 67 68 |
# File 'lib/trak_flow/models/task.rb', line 66 def closed? status == "closed" || status == "tombstone" end |
#discardable? ⇒ Boolean
100 101 102 |
# File 'lib/trak_flow/models/task.rb', line 100 def discardable? ephemeral? end |
#ephemeral? ⇒ Boolean
92 93 94 |
# File 'lib/trak_flow/models/task.rb', line 92 def ephemeral? !!ephemeral end |
#epic? ⇒ Boolean
78 79 80 |
# File 'lib/trak_flow/models/task.rb', line 78 def epic? type == "epic" end |
#errors ⇒ Object
46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/trak_flow/models/task.rb', line 46 def errors errs = [] errs << "Title is required" if title.nil? || title.strip.empty? errs << "Invalid status: #{status}" unless VALID_STATUSES.include?(status) errs << "Invalid priority: #{priority}" unless VALID_PRIORITIES.include?(priority) errs << "Invalid type: #{type}" unless VALID_TYPES.include?(type) errs << "Plans cannot be ephemeral" if plan && ephemeral errs << "Plans cannot change status" if plan && status != "open" errs << "Plans cannot be derived from other Plans" if plan && source_plan_id errs end |
#executable? ⇒ Boolean
96 97 98 |
# File 'lib/trak_flow/models/task.rb', line 96 def executable? !plan? end |
#in_progress? ⇒ Boolean
70 71 72 |
# File 'lib/trak_flow/models/task.rb', line 70 def in_progress? status == "in_progress" end |
#open? ⇒ Boolean
62 63 64 |
# File 'lib/trak_flow/models/task.rb', line 62 def open? status == "open" end |
#plan? ⇒ Boolean
Plan/Workflow role predicates
84 85 86 |
# File 'lib/trak_flow/models/task.rb', line 84 def plan? !!plan end |
#reopen!(reason: nil) ⇒ Object
111 112 113 114 115 116 |
# File 'lib/trak_flow/models/task.rb', line 111 def reopen!(reason: nil) self.status = "open" self.closed_at = nil self.notes = "#{notes}\n[Reopened] #{reason}".strip if reason touch! end |
#to_h ⇒ Object
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'lib/trak_flow/models/task.rb', line 134 def to_h { id: id, title: title, description: description, status: status, priority: priority, type: type, assignee: assignee, parent_id: parent_id, created_at: created_at&.iso8601, updated_at: updated_at&.iso8601, closed_at: closed_at&.iso8601, content_hash: content_hash, plan: plan, source_plan_id: source_plan_id, ephemeral: ephemeral, notes: notes }.compact end |
#to_json(*args) ⇒ Object
155 156 157 |
# File 'lib/trak_flow/models/task.rb', line 155 def to_json(*args) Oj.dump(to_h, mode: :compat) end |
#touch! ⇒ Object
118 119 120 121 |
# File 'lib/trak_flow/models/task.rb', line 118 def touch! self.updated_at = Time.now.utc update_content_hash! end |
#update_content_hash! ⇒ Object
130 131 132 |
# File 'lib/trak_flow/models/task.rb', line 130 def update_content_hash! self.content_hash = IdGenerator.content_hash(to_h.except(:content_hash, :updated_at)) end |
#valid? ⇒ Boolean
42 43 44 |
# File 'lib/trak_flow/models/task.rb', line 42 def valid? errors.empty? end |
#validate! ⇒ Object
58 59 60 |
# File 'lib/trak_flow/models/task.rb', line 58 def validate! raise ValidationError, errors.join(", ") unless valid? end |
#workflow? ⇒ Boolean
88 89 90 |
# File 'lib/trak_flow/models/task.rb', line 88 def workflow? source_plan_id && !source_plan_id.to_s.empty? && !plan? end |