Class: PlanMyStuff::Comment
- Inherits:
-
ApplicationRecord
- Object
- ApplicationRecord
- PlanMyStuff::Comment
- Defined in:
- lib/plan_my_stuff/comment.rb
Overview
Wraps a GitHub comment with parsed PMS metadata. Class methods provide the public API for CRUD operations.
Follows an ActiveRecord-style pattern:
-
‘Comment.new(**attrs)` creates an unpersisted instance
-
‘Comment.create!` / `Comment.list` return persisted instances
-
‘comment.save!` / `comment.update!` / `comment.reload` for persistence
Instance Attribute Summary collapse
-
#body ⇒ String
Comment body without the metadata HTML comment.
-
#id ⇒ Integer
readonly
GitHub comment ID.
-
#issue ⇒ PlanMyStuff::Issue
Parent issue.
-
#metadata ⇒ PlanMyStuff::CommentMetadata
readonly
Parsed metadata (empty when no PMS metadata present).
-
#raw_body ⇒ String
readonly
Full body as stored on GitHub.
-
#visibility ⇒ Symbol?
Returns the comment visibility as a symbol.
Class Method Summary collapse
-
.create!(issue:, body:, user: nil, visibility: :public, custom_fields: {}, skip_responded: false, issue_body: false) ⇒ PlanMyStuff::Comment
Creates a comment on a GitHub issue with PMS metadata and a visible header.
-
.find(id, issue:) ⇒ PlanMyStuff::Comment
Finds a single comment by ID, given its parent issue.
-
.list(issue:, pms_only: false) ⇒ Array<PlanMyStuff::Comment>
Lists comments on a GitHub issue, optionally filtering to PMS-only comments.
-
.update!(id:, repo:, body:) ⇒ Object
Updates an existing GitHub comment body.
Instance Method Summary collapse
-
#body_without_header ⇒ String
Returns the comment body with the header stripped.
-
#header ⇒ String?
Extracts the ‘### Name at timestamp:` header line from the comment body.
-
#initialize(**attrs) ⇒ Comment
constructor
A new instance of Comment.
- #pms_comment? ⇒ Boolean
-
#reload ⇒ self
Re-fetches this comment from GitHub and updates all local attributes.
-
#save! ⇒ self
Persists the comment.
-
#update!(**attrs) ⇒ self
Updates this comment on GitHub.
-
#visible_to?(user) ⇒ Boolean
Checks if the comment is visible to the given user.
Methods inherited from ApplicationRecord
Constructor Details
#initialize(**attrs) ⇒ Comment
Returns a new instance of Comment.
179 180 181 182 183 184 |
# File 'lib/plan_my_stuff/comment.rb', line 179 def initialize(**attrs) @id = attrs.delete(:id) @raw_body = nil @metadata = CommentMetadata.new super end |
Instance Attribute Details
#body ⇒ String
Returns comment body without the metadata HTML comment.
20 21 22 |
# File 'lib/plan_my_stuff/comment.rb', line 20 def body @body end |
#id ⇒ Integer (readonly)
Returns GitHub comment ID.
13 14 15 |
# File 'lib/plan_my_stuff/comment.rb', line 13 def id @id end |
#issue ⇒ PlanMyStuff::Issue
Returns parent issue.
22 23 24 |
# File 'lib/plan_my_stuff/comment.rb', line 22 def issue @issue end |
#metadata ⇒ PlanMyStuff::CommentMetadata (readonly)
Returns parsed metadata (empty when no PMS metadata present).
17 18 19 |
# File 'lib/plan_my_stuff/comment.rb', line 17 def @metadata end |
#raw_body ⇒ String (readonly)
Returns full body as stored on GitHub.
15 16 17 |
# File 'lib/plan_my_stuff/comment.rb', line 15 def raw_body @raw_body end |
#visibility ⇒ Symbol?
Returns the comment visibility as a symbol. Uses the locally set value if present, otherwise falls back to metadata.
254 255 256 |
# File 'lib/plan_my_stuff/comment.rb', line 254 def visibility @visibility || .visibility&.to_sym end |
Class Method Details
.create!(issue:, body:, user: nil, visibility: :public, custom_fields: {}, skip_responded: false, issue_body: false) ⇒ PlanMyStuff::Comment
Creates a comment on a GitHub issue with PMS metadata and a visible header.
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/plan_my_stuff/comment.rb', line 38 def create!( issue:, body:, user: nil, visibility: :public, custom_fields: {}, skip_responded: false, issue_body: false ) resolved_user = UserResolver.resolve(user) visibility = resolve_visibility(visibility, resolved_user) = CommentMetadata.build( user: resolved_user, visibility: visibility.to_s, custom_fields: custom_fields, issue_body: issue_body, ) header = build_header(resolved_user) full_body = "#{header}\n\n#{body}" serialized_body = MetadataParser.serialize(.to_h, full_body) result = PlanMyStuff.client.rest(:add_comment, issue.repo, issue.number, serialized_body) mark_issue_responded_if_first_support_comment(issue, resolved_user) unless skip_responded build(result, issue: issue) end |
.find(id, issue:) ⇒ PlanMyStuff::Comment
Finds a single comment by ID, given its parent issue.
86 87 88 89 |
# File 'lib/plan_my_stuff/comment.rb', line 86 def find(id, issue:) github_comment = PlanMyStuff.client.rest(:issue_comment, issue.repo, id) build(github_comment, issue: issue) end |
.list(issue:, pms_only: false) ⇒ Array<PlanMyStuff::Comment>
Lists comments on a GitHub issue, optionally filtering to PMS-only comments.
98 99 100 101 102 103 |
# File 'lib/plan_my_stuff/comment.rb', line 98 def list(issue:, pms_only: false) github_comments = PlanMyStuff.client.rest(:issue_comments, issue.repo, issue.number) comments = github_comments.map { |gc| build(gc, issue: issue) } pms_only ? comments.select(&:pms_comment?) : comments end |
.update!(id:, repo:, body:) ⇒ Object
Updates an existing GitHub comment body.
75 76 77 |
# File 'lib/plan_my_stuff/comment.rb', line 75 def update!(id:, repo:, body:) PlanMyStuff.client.rest(:update_comment, repo, id, body) end |
Instance Method Details
#body_without_header ⇒ String
Returns the comment body with the header stripped.
290 291 292 |
# File 'lib/plan_my_stuff/comment.rb', line 290 def body_without_header (body || '').sub(/\A###\s.+?:\s*\n\n/, '') end |
#header ⇒ String?
Extracts the ‘### Name at timestamp:` header line from the comment body.
281 282 283 284 |
# File 'lib/plan_my_stuff/comment.rb', line 281 def header match = (body || '').match(/\A(###\s.+?:\s*)\n/) match&.captures&.first&.strip end |
#pms_comment? ⇒ Boolean
245 246 247 |
# File 'lib/plan_my_stuff/comment.rb', line 245 def pms_comment? .schema_version.present? end |
#reload ⇒ self
Re-fetches this comment from GitHub and updates all local attributes.
238 239 240 241 242 |
# File 'lib/plan_my_stuff/comment.rb', line 238 def reload github_comment = PlanMyStuff.client.rest(:issue_comment, issue.repo, id) hydrate_from_github(github_comment, issue: issue) self end |
#save! ⇒ self
Persists the comment. Creates if new, updates if persisted.
192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/plan_my_stuff/comment.rb', line 192 def save! if new_record? created = self.class.create!( issue: issue, body: body, visibility: visibility || :public, ) hydrate_from_comment(created) else update!(body: body) end self end |
#update!(**attrs) ⇒ self
Updates this comment on GitHub. Raises StaleObjectError if the remote has been modified since this instance was loaded.
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
# File 'lib/plan_my_stuff/comment.rb', line 216 def update!(**attrs) raise_if_stale! new_body = attrs[:body] || body = .to_h if attrs.key?(:visibility) new_visibility = attrs[:visibility].to_s [:visibility] = new_visibility [:updated_at] = Time.now.utc.iso8601 end serialized = MetadataParser.serialize(, new_body) self.class.update!(id: id, repo: issue.repo, body: serialized) reload end |
#visible_to?(user) ⇒ Boolean
Checks if the comment is visible to the given user. Public PMS comments: visible to everyone the parent issue is visible to. Internal PMS comments: visible only to support users. Non-PMS comments: visible only to support users.
267 268 269 270 271 272 273 274 275 |
# File 'lib/plan_my_stuff/comment.rb', line 267 def visible_to?(user) resolved = PMS::UserResolver.resolve(user) if pms_comment? issue.visible_to?(resolved) && (visibility != :internal || PMS::UserResolver.support?(resolved)) else PMS::UserResolver.support?(resolved) end end |