Module: Docsmith::VersionManager

Defined in:
lib/docsmith/version_manager.rb

Overview

Service object for all version lifecycle operations. The Versionable mixin delegates here after resolving the shadow document. Always receives a Docsmith::Document instance.

Class Method Summary collapse

Class Method Details

.restore!(document, version:, author:, config: nil) ⇒ Docsmith::DocumentVersion

Restore a previous version by creating a new version with its content. Fires :version_restored (not :version_created). Never mutates existing versions.

Parameters:

  • document (Docsmith::Document)
  • version (Integer)

    version_number to restore from

  • author (Object, nil)
  • config (Hash) (defaults to: nil)

    resolved config

Returns:

Raises:



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/docsmith/version_manager.rb', line 59

def self.restore!(document, version:, author:, config: nil)
  config      ||= Configuration.resolve({}, Docsmith.configuration)
  from_version  = document.document_versions.find_by(version_number: version)
  raise VersionNotFound, "Version #{version} not found on this document" unless from_version

  next_num = document.versions_count + 1

  new_version = DocumentVersion.create!(
    document:       document,
    version_number: next_num,
    content:        from_version.content,
    content_type:   document.content_type,
    author:         author,
    change_summary: "Restored from v#{version}",
    metadata:       {}
  )

  document.update_columns(
    content:           from_version.content,
    versions_count:    next_num,
    last_versioned_at: Time.current
  )

  record = document.subject || document
  Events::Notifier.instrument(:version_restored,
    record: record, document: document, version: new_version,
    author: author, from_version: from_version)

  new_version
end

.save!(document, author:, summary: nil, config: nil) ⇒ Docsmith::DocumentVersion?

Create a new DocumentVersion snapshot. Returns nil if content is identical to the latest version (string == check).

Parameters:

  • document (Docsmith::Document)
  • author (Object, nil)
  • summary (String, nil) (defaults to: nil)
  • config (Hash) (defaults to: nil)

    resolved config

Returns:



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/docsmith/version_manager.rb', line 16

def self.save!(document, author:, summary: nil, config: nil)
  config  ||= Configuration.resolve({}, Docsmith.configuration)
  current   = document.content.to_s
  latest    = document.document_versions.last

  return nil if latest && latest.content == current

  next_num = document.versions_count + 1

  version = DocumentVersion.create!(
    document:       document,
    version_number: next_num,
    content:        current,
    content_type:   document.content_type,
    author:         author,
    change_summary: summary,
    metadata:       {}
  )

  document.update_columns(
    versions_count:    next_num,
    last_versioned_at: Time.current
  )
  document.versions_count = next_num

  prune_if_needed!(document, version, config) if config[:max_versions]

  record = document.subject || document
  Events::Notifier.instrument(:version_created,
    record: record, document: document, version: version, author: author)

  version
end

.tag!(document, version:, name:, author:) ⇒ Docsmith::VersionTag

Tag a specific version with a name unique to this document.

Parameters:

  • document (Docsmith::Document)
  • version (Integer)

    version_number to tag

  • name (String)

    unique per document

  • author (Object, nil)

Returns:

Raises:



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/docsmith/version_manager.rb', line 99

def self.tag!(document, version:, name:, author:)
  version_record = document.document_versions.find_by(version_number: version)
  raise VersionNotFound, "Version #{version} not found on this document" unless version_record

  if VersionTag.exists?(document_id: document.id, name: name)
    raise TagAlreadyExists, "Tag '#{name}' already exists on this document"
  end

  tag = VersionTag.create!(
    document: document,
    version:  version_record,
    name:     name,
    author:   author
  )

  record = document.subject || document
  Events::Notifier.instrument(:version_tagged,
    record: record, document: document, version: version_record,
    author: author, tag_name: name)

  tag
end