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
- NILABLE_ATTRIBUTES =
Attributes that default to nil when not given.
%i[id title assignee parent_id closed_at content_hash source_plan_id].freeze
- ATTRIBUTE_DEFAULTS =
Attributes with a non-nil default.
{ description: "", status: "open", priority: 2, type: "task", plan: false, ephemeral: false, notes: "" }.freeze
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.
37 38 39 40 41 42 43 44 |
# File 'lib/trak_flow/models/task.rb', line 37 def initialize(attrs = {}) NILABLE_ATTRIBUTES.each { |key| instance_variable_set("@#{key}", attrs[key]) } ATTRIBUTE_DEFAULTS.each { |key, default| instance_variable_set("@#{key}", attrs[key] || default) } now = Time.now.utc @created_at = attrs[:created_at] || now @updated_at = attrs[:updated_at] || now 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
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/trak_flow/models/task.rb', line 164 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
186 187 188 |
# File 'lib/trak_flow/models/task.rb', line 186 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
127 128 129 130 131 132 |
# File 'lib/trak_flow/models/task.rb', line 127 def append_trace(action, ) = Time.now.utc.iso8601 entry = "[#{}] [#{action}] #{}" self.notes = "#{notes}\n#{entry}".strip touch! end |
#blocked? ⇒ Boolean
78 79 80 |
# File 'lib/trak_flow/models/task.rb', line 78 def blocked? status == "blocked" end |
#close!(reason: nil) ⇒ Object
108 109 110 111 112 113 |
# File 'lib/trak_flow/models/task.rb', line 108 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
70 71 72 |
# File 'lib/trak_flow/models/task.rb', line 70 def closed? %w[closed tombstone].include?(status) end |
#discardable? ⇒ Boolean
104 105 106 |
# File 'lib/trak_flow/models/task.rb', line 104 def discardable? ephemeral? end |
#ephemeral? ⇒ Boolean
96 97 98 |
# File 'lib/trak_flow/models/task.rb', line 96 def ephemeral? !!ephemeral end |
#epic? ⇒ Boolean
82 83 84 |
# File 'lib/trak_flow/models/task.rb', line 82 def epic? type == "epic" end |
#errors ⇒ Object
50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/trak_flow/models/task.rb', line 50 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
100 101 102 |
# File 'lib/trak_flow/models/task.rb', line 100 def executable? !plan? end |
#in_progress? ⇒ Boolean
74 75 76 |
# File 'lib/trak_flow/models/task.rb', line 74 def in_progress? status == "in_progress" end |
#open? ⇒ Boolean
66 67 68 |
# File 'lib/trak_flow/models/task.rb', line 66 def open? status == "open" end |
#plan? ⇒ Boolean
Plan/Workflow role predicates
88 89 90 |
# File 'lib/trak_flow/models/task.rb', line 88 def plan? !!plan end |
#reopen!(reason: nil) ⇒ Object
115 116 117 118 119 120 |
# File 'lib/trak_flow/models/task.rb', line 115 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
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/trak_flow/models/task.rb', line 138 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
159 160 161 |
# File 'lib/trak_flow/models/task.rb', line 159 def to_json(*args) Oj.dump(to_h, mode: :compat) end |
#touch! ⇒ Object
122 123 124 125 |
# File 'lib/trak_flow/models/task.rb', line 122 def touch! self.updated_at = Time.now.utc update_content_hash! end |
#update_content_hash! ⇒ Object
134 135 136 |
# File 'lib/trak_flow/models/task.rb', line 134 def update_content_hash! self.content_hash = IdGenerator.content_hash(to_h.except(:content_hash, :updated_at)) end |
#valid? ⇒ Boolean
46 47 48 |
# File 'lib/trak_flow/models/task.rb', line 46 def valid? errors.empty? end |
#validate! ⇒ Object
62 63 64 |
# File 'lib/trak_flow/models/task.rb', line 62 def validate! raise ValidationError, errors.join(", ") unless valid? end |
#workflow? ⇒ Boolean
92 93 94 |
# File 'lib/trak_flow/models/task.rb', line 92 def workflow? source_plan_id && !source_plan_id.to_s.empty? && !plan? end |