Module: Docsmith::Versionable
- Defined in:
- lib/docsmith/versionable.rb
Overview
ActiveRecord mixin that adds full versioning to any model.
Usage:
class Article < ApplicationRecord
include Docsmith::Versionable
docsmith_config { content_field :body; content_type :markdown }
end
Defined Under Namespace
Modules: ClassMethods
Class Method Summary collapse
Instance Method Summary collapse
-
#add_comment!(version:, body:, author:, anchor: nil, parent: nil) ⇒ Docsmith::Comments::Comment
Adds a comment to a specific version of this document.
-
#auto_save_version!(author: nil) ⇒ Docsmith::DocumentVersion?
Debounced auto-save.
-
#comments ⇒ ActiveRecord::Relation<Docsmith::Comments::Comment>
Returns all comments across all versions of this document.
-
#comments_on(version:, type: nil) ⇒ ActiveRecord::Relation<Docsmith::Comments::Comment>
Returns comments on a specific version, optionally filtered by anchor type.
-
#current_version ⇒ Docsmith::DocumentVersion?
Latest version.
-
#diff_between(from_version, to_version) ⇒ Docsmith::Diff::Result
Computes a diff between two named versions.
-
#diff_from(version_number) ⇒ Docsmith::Diff::Result
Computes a diff from version N to the current (latest) version.
-
#migrate_comments!(from:, to:) ⇒ void
Migrates top-level comments from one version to another.
-
#restore_version!(number, author:) ⇒ Docsmith::DocumentVersion
Restore to a previous version.
-
#save_version!(author:, summary: nil) ⇒ Docsmith::DocumentVersion?
Create a new DocumentVersion snapshot of this record's content.
-
#tag_version!(number, name:, author:) ⇒ Docsmith::VersionTag
Tag a specific version.
- #tagged_version(tag_name) ⇒ Docsmith::DocumentVersion?
-
#unresolved_comments ⇒ ActiveRecord::Relation<Docsmith::Comments::Comment>
Returns all unresolved comments across all versions.
- #version(number) ⇒ Docsmith::DocumentVersion?
-
#version_tags(number) ⇒ Array<String>
Tag names on that version.
-
#versions ⇒ ActiveRecord::Relation<Docsmith::DocumentVersion>
Ordered by version_number.
Class Method Details
.included(base) ⇒ Object
12 13 14 15 |
# File 'lib/docsmith/versionable.rb', line 12 def self.included(base) base.extend(ClassMethods) base.after_save(:_docsmith_auto_save_callback) end |
Instance Method Details
#add_comment!(version:, body:, author:, anchor: nil, parent: nil) ⇒ Docsmith::Comments::Comment
Adds a comment to a specific version of this document.
164 165 166 167 168 169 170 171 172 173 |
# File 'lib/docsmith/versionable.rb', line 164 def add_comment!(version:, body:, author:, anchor: nil, parent: nil) Comments::Manager.add!( _docsmith_document, version_number: version, body: body, author: , anchor: anchor, parent: parent ) end |
#auto_save_version!(author: nil) ⇒ Docsmith::DocumentVersion?
Debounced auto-save. Returns nil if debounce window has not elapsed OR content is unchanged. Both non-save cases return nil. auto_save: false in config causes this to always return nil.
61 62 63 64 65 66 67 |
# File 'lib/docsmith/versionable.rb', line 61 def auto_save_version!(author: nil) config = self.class.docsmith_resolved_config return nil unless config[:auto_save] _sync_docsmith_content! Docsmith::AutoSave.call(_docsmith_document, author: , config: config) end |
#comments ⇒ ActiveRecord::Relation<Docsmith::Comments::Comment>
Returns all comments across all versions of this document.
178 179 180 181 182 |
# File 'lib/docsmith/versionable.rb', line 178 def comments doc = _docsmith_document Comments::Comment.joins(:version) .where(docsmith_versions: { document_id: doc.id }) end |
#comments_on(version:, type: nil) ⇒ ActiveRecord::Relation<Docsmith::Comments::Comment>
Returns comments on a specific version, optionally filtered by anchor type.
189 190 191 192 193 194 195 |
# File 'lib/docsmith/versionable.rb', line 189 def comments_on(version:, type: nil) doc = _docsmith_document dv = Docsmith::DocumentVersion.find_by!(document: doc, version_number: version) rel = Comments::Comment.where(version: dv) rel = rel.where(anchor_type: type.to_s) if type rel end |
#current_version ⇒ Docsmith::DocumentVersion?
Returns latest version.
75 76 77 |
# File 'lib/docsmith/versionable.rb', line 75 def current_version _docsmith_document.current_version end |
#diff_between(from_version, to_version) ⇒ Docsmith::Diff::Result
Computes a diff between two named versions.
149 150 151 152 153 154 |
# File 'lib/docsmith/versionable.rb', line 149 def diff_between(from_version, to_version) doc = _docsmith_document v_from = Docsmith::DocumentVersion.find_by!(document: doc, version_number: from_version) v_to = Docsmith::DocumentVersion.find_by!(document: doc, version_number: to_version) Docsmith::Diff.between(v_from, v_to) end |
#diff_from(version_number) ⇒ Docsmith::Diff::Result
Computes a diff from version N to the current (latest) version.
136 137 138 139 140 141 |
# File 'lib/docsmith/versionable.rb', line 136 def diff_from(version_number) doc = _docsmith_document v_from = Docsmith::DocumentVersion.find_by!(document: doc, version_number: version_number) v_to = Docsmith::DocumentVersion.where(document_id: doc.id).order(version_number: :desc).first! Docsmith::Diff.between(v_from, v_to) end |
#migrate_comments!(from:, to:) ⇒ void
This method returns an undefined value.
Migrates top-level comments from one version to another.
209 210 211 |
# File 'lib/docsmith/versionable.rb', line 209 def migrate_comments!(from:, to:) Comments::Migrator.migrate!(_docsmith_document, from: from, to: to) end |
#restore_version!(number, author:) ⇒ Docsmith::DocumentVersion
Restore to a previous version. Creates a new version with the old content. Syncs restored content back to the model's content_field via update_column (bypasses after_save to prevent a duplicate auto-save). Never mutates existing versions.
94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/docsmith/versionable.rb', line 94 def restore_version!(number, author:) result = Docsmith::VersionManager.restore!( _docsmith_document, version: number, author: , config: self.class.docsmith_resolved_config ) field = self.class.docsmith_resolved_config[:content_field] update_column(field, _docsmith_document.reload.content) result end |
#save_version!(author:, summary: nil) ⇒ Docsmith::DocumentVersion?
Create a new DocumentVersion snapshot of this record's content. Returns nil if content is identical to the latest version. Raises Docsmith::InvalidContentField if content_field returns a non-String and no content_extractor is configured.
45 46 47 48 49 50 51 52 53 |
# File 'lib/docsmith/versionable.rb', line 45 def save_version!(author:, summary: nil) _sync_docsmith_content! Docsmith::VersionManager.save!( _docsmith_document, author: , summary: summary, config: self.class.docsmith_resolved_config ) end |
#tag_version!(number, name:, author:) ⇒ Docsmith::VersionTag
Tag a specific version. Names are unique per document.
111 112 113 114 |
# File 'lib/docsmith/versionable.rb', line 111 def tag_version!(number, name:, author:) Docsmith::VersionManager.tag!( _docsmith_document, version: number, name: name, author: ) end |
#tagged_version(tag_name) ⇒ Docsmith::DocumentVersion?
118 119 120 121 |
# File 'lib/docsmith/versionable.rb', line 118 def tagged_version(tag_name) tag = _docsmith_document..find_by(name: tag_name) tag&.version end |
#unresolved_comments ⇒ ActiveRecord::Relation<Docsmith::Comments::Comment>
Returns all unresolved comments across all versions.
200 201 202 |
# File 'lib/docsmith/versionable.rb', line 200 def unresolved_comments comments.merge(Comments::Comment.unresolved) end |
#version(number) ⇒ Docsmith::DocumentVersion?
81 82 83 |
# File 'lib/docsmith/versionable.rb', line 81 def version(number) _docsmith_document.document_versions.find_by(version_number: number) end |
#version_tags(number) ⇒ Array<String>
Returns tag names on that version.
125 126 127 128 129 |
# File 'lib/docsmith/versionable.rb', line 125 def (number) ver = version(number) return [] unless ver ver..pluck(:name) end |
#versions ⇒ ActiveRecord::Relation<Docsmith::DocumentVersion>
Returns ordered by version_number.
70 71 72 |
# File 'lib/docsmith/versionable.rb', line 70 def versions _docsmith_document.document_versions end |