Module: Labimotion::TemplateDoi::ClassMethods
- Defined in:
- lib/labimotion/models/concerns/template_doi.rb
Overview
ActiveSupport::Concern extends this into the including class, so every method below becomes a class method on the host's Doi.
Instance Method Summary collapse
-
#build_labimotion_suffix(record, version = nil) ⇒ Object
Deterministic DOI suffix for a LabIMotion template klass.
-
#labimotion_doi_metadata(record, version = nil) ⇒ Object
Metadata stamped on a reserved template DOI so the version it represents survives on the record (used to gate reserving the next version).
-
#labimotion_doi_publication(doi) ⇒ Object
The publication metadata a released template DOI was published with.
-
#labimotion_doi_version(doi) ⇒ Object
The DOI version (next-major integer) recorded on a reserved template DOI.
-
#labimotion_dois(record) ⇒ Object
The DOIs reserved for a LabIMotion template, in reservation order.
-
#labimotion_latest_doi(record) ⇒ Object
The current (most recently reserved) DOI for a template, or nil.
-
#labimotion_metadata_with_publication(doi, publication) ⇒ Object
The DOI's metadata with the publication snapshotted into it, keeping the DOI version already stamped there.
- #labimotion_suffix_parts(record) ⇒ Object
-
#labimotion_version_segment(record, version = nil) ⇒ Object
The DOI version segment for a template version.
-
#sanitize_doi_part(value) ⇒ Object
Keeps a suffix segment DOI-safe: trims, collapses whitespace to hyphens and drops anything outside [A-Za-z0-9._-] (colons stripped, as elsewhere here).
Instance Method Details
#build_labimotion_suffix(record, version = nil) ⇒ Object
Deterministic DOI suffix for a LabIMotion template klass. The same suffix is used at reserve and at release time, so both share one DOI:
element -> labimotion/element/<name>/<identifier>/<doi_version>
segment -> labimotion/segment/<element>/<identifier>/<doi_version>
dataset -> labimotion/dataset/<ols_term_id>/<identifier>/<doi_version>
<identifier> is the first UUID group (8 hex chars) of the template's
identifier/uuid, falling back to the record id. <doi_version> is the DOI
version (see .labimotion_version_segment). Callers may pass an explicit
template version; otherwise the record's current version is used.
37 38 39 40 41 42 43 44 45 46 |
# File 'lib/labimotion/models/concerns/template_doi.rb', line 37 def build_labimotion_suffix(record, version = nil) parts = labimotion_suffix_parts(record) raise ArgumentError, "unsupported template: #{record.class}" if parts.nil? segment = labimotion_version_segment(record, version) return nil if segment.blank? segments = parts.map { |part| sanitize_doi_part(part) }.reject(&:empty?) "#{segments.join('/')}/#{segment}" end |
#labimotion_doi_metadata(record, version = nil) ⇒ Object
Metadata stamped on a reserved template DOI so the version it represents survives on the record (used to gate reserving the next version).
81 82 83 |
# File 'lib/labimotion/models/concerns/template_doi.rb', line 81 def (record, version = nil) { 'labimotion' => { 'doi_version' => labimotion_version_segment(record, version) } } end |
#labimotion_doi_publication(doi) ⇒ Object
The publication metadata a released template DOI was published with. Nil while the DOI is still reserved, and for DOIs released before snapshots were kept — callers fall back to the template's current publication in both cases.
89 90 91 |
# File 'lib/labimotion/models/concerns/template_doi.rb', line 89 def labimotion_doi_publication(doi) doi..to_h.dig('labimotion', 'publication') end |
#labimotion_doi_version(doi) ⇒ Object
The DOI version (next-major integer) recorded on a reserved template DOI.
75 76 77 |
# File 'lib/labimotion/models/concerns/template_doi.rb', line 75 def labimotion_doi_version(doi) doi..to_h.dig('labimotion', 'doi_version') end |
#labimotion_dois(record) ⇒ Object
The DOIs reserved for a LabIMotion template, in reservation order.
65 66 67 |
# File 'lib/labimotion/models/concerns/template_doi.rb', line 65 def labimotion_dois(record) where(doiable_id: record.id, doiable_type: record.class.name).order(:id).to_a end |
#labimotion_latest_doi(record) ⇒ Object
The current (most recently reserved) DOI for a template, or nil.
70 71 72 |
# File 'lib/labimotion/models/concerns/template_doi.rb', line 70 def labimotion_latest_doi(record) labimotion_dois(record).last end |
#labimotion_metadata_with_publication(doi, publication) ⇒ Object
The DOI's metadata with the publication snapshotted into it, keeping the DOI version already stamped there. Taken at release: the template's publication keeps being edited for the next version, and this version must stop tracking those edits.
97 98 99 100 101 102 103 |
# File 'lib/labimotion/models/concerns/template_doi.rb', line 97 def (doi, publication) = doi..to_h # Deep-duped: the snapshot must not alias the template's publication, # which goes on being edited for the next version. labimotion = (['labimotion'] || {}).merge('publication' => publication.deep_dup) .merge('labimotion' => labimotion) end |
#labimotion_suffix_parts(record) ⇒ Object
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/labimotion/models/concerns/template_doi.rb', line 105 def labimotion_suffix_parts(record) # identifier/uuid may both be blank for a draft, which would collapse the # scope (colliding across templates). Fall back to the stable record id so # every template gets a unique, deterministic suffix. Resolved lazily so an # unsupported record (no #id) still falls through to the ArgumentError in the # caller. The identifier is shortened to its first UUID group (8 hex chars). # A segment's <element> is the name of the ElementKlass it belongs to. identifier = lambda do raw = record.try(:identifier).presence || record.try(:uuid).presence || record.id raw.to_s.split('-').first end case record when ::Labimotion::ElementKlass [LABIMOTION_DOI_NAMESPACE, 'element', record.name, identifier.call] when ::Labimotion::SegmentKlass [LABIMOTION_DOI_NAMESPACE, 'segment', record.element_klass&.name, identifier.call] when ::Labimotion::DatasetKlass [LABIMOTION_DOI_NAMESPACE, 'dataset', record.ols_term_id, identifier.call] end end |
#labimotion_version_segment(record, version = nil) ⇒ Object
The DOI version segment for a template version. A DOI is published per major release: the .0 release opens that version (X.0 -> "X") and later minor revisions roll into the NEXT DOI (X.y, y>=1 -> "X+1"). Sub-1.0 and unversioned/blank templates map to the first DOI (v1). 0.x -> "1" 1.0 -> "1" 1.1..2.0 -> "2" 2.1..3.0 -> "3"
53 54 55 56 57 58 59 60 61 62 |
# File 'lib/labimotion/models/concerns/template_doi.rb', line 53 def labimotion_version_segment(record, version = nil) raw = (version.presence || record.try(:version)).to_s.strip parts = raw.split('.') major = parts[0].to_i minor = parts[1].to_i return '1' if major.zero? return major.to_s if minor.zero? (major + 1).to_s end |
#sanitize_doi_part(value) ⇒ Object
Keeps a suffix segment DOI-safe: trims, collapses whitespace to hyphens and drops anything outside [A-Za-z0-9._-] (colons stripped, as elsewhere here).
128 129 130 |
# File 'lib/labimotion/models/concerns/template_doi.rb', line 128 def sanitize_doi_part(value) value.to_s.strip.gsub(/\s+/, '-').gsub(/[^A-Za-z0-9._-]/, '') end |