labimotion 2.2.0.rc18 → 2.2.0.rc19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bf9125138e1e1d1e52a978fd85f63e67dd1339cf683296bdf0680c86dd9cc16b
|
|
4
|
+
data.tar.gz: e910e27b0a70cc1e6995142a23af5fba0f59a9313bd13d5eea01092f42991c85
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ee02aa627ad14085e7860c8f017442d3733a764883781cd6e5156b5a4cd759b41a9697612fd37238437b4c7ef6671f5e43e355243c6cf70061ec555ebb46b7b8
|
|
7
|
+
data.tar.gz: de67299ee82e4e59b8dcce459265b3905338fef48c60271d86b653f00279a8e749afbeb5ea53681a2e0e2ca7a9c4a4386073ec9fe29f17f96504ff1a7ea9cf50
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<resource xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://datacite.org/schema/kernel-4" xsi:schemaLocation="http://datacite.org/schema/kernel-4 https://schema.datacite.org/meta/kernel-4/metadata.xsd">
|
|
3
|
+
<identifier identifierType="DOI">https://dx.doi.org/<%= full_doi %></identifier>
|
|
4
|
+
<creators>
|
|
5
|
+
<% if creators.empty? %>
|
|
6
|
+
<creator>
|
|
7
|
+
<creatorName>(:unav)</creatorName>
|
|
8
|
+
</creator>
|
|
9
|
+
<% end %>
|
|
10
|
+
<% creators.each do |creator| %>
|
|
11
|
+
<creator>
|
|
12
|
+
<creatorName nameType="Personal"><%= creator['familyName'] %>, <%= creator['givenName'] %></creatorName>
|
|
13
|
+
<givenName><%= creator['givenName'] %></givenName>
|
|
14
|
+
<familyName><%= creator['familyName'] %></familyName>
|
|
15
|
+
<% if creator['orcid'].present? %>
|
|
16
|
+
<nameIdentifier schemeURI="https://orcid.org/" nameIdentifierScheme="ORCID"><%= creator['orcid'] %></nameIdentifier>
|
|
17
|
+
<% end %>
|
|
18
|
+
<% if creator['affiliation'].present? %>
|
|
19
|
+
<affiliation><%= creator['affiliation'] %></affiliation>
|
|
20
|
+
<% end %>
|
|
21
|
+
</creator>
|
|
22
|
+
<% end %>
|
|
23
|
+
</creators>
|
|
24
|
+
<titles>
|
|
25
|
+
<title xml:lang="en-US"><%= title %></title>
|
|
26
|
+
</titles>
|
|
27
|
+
<%= render_publisher(publisher_config) %>
|
|
28
|
+
<publicationYear><%= publication_year %></publicationYear>
|
|
29
|
+
<subjects>
|
|
30
|
+
<subject>Chemistry</subject>
|
|
31
|
+
</subjects>
|
|
32
|
+
<% if contributor %>
|
|
33
|
+
<contributors>
|
|
34
|
+
<contributor contributorType="Researcher">
|
|
35
|
+
<contributorName nameType="Personal"><%= contributor['familyName'] %>, <%= contributor['givenName'] %></contributorName>
|
|
36
|
+
<givenName><%= contributor['givenName'] %></givenName>
|
|
37
|
+
<familyName><%= contributor['familyName'] %></familyName>
|
|
38
|
+
<% if contributor['orcid'].present? %>
|
|
39
|
+
<nameIdentifier schemeURI="https://orcid.org/" nameIdentifierScheme="ORCID"><%= contributor['orcid'] %></nameIdentifier>
|
|
40
|
+
<% end %>
|
|
41
|
+
</contributor>
|
|
42
|
+
</contributors>
|
|
43
|
+
<% end %>
|
|
44
|
+
<language>en</language>
|
|
45
|
+
<resourceType resourceTypeGeneral="Model"><%= resource_label %></resourceType>
|
|
46
|
+
<version><%= version %></version>
|
|
47
|
+
<rightsList>
|
|
48
|
+
<rights><%= license %></rights>
|
|
49
|
+
</rightsList>
|
|
50
|
+
<descriptions>
|
|
51
|
+
<% if description.present? %>
|
|
52
|
+
<description xml:lang="en-US" descriptionType="Abstract"><%= description %></description>
|
|
53
|
+
<% end %>
|
|
54
|
+
</descriptions>
|
|
55
|
+
</resource>
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# TemplateDoi concern
|
|
4
|
+
#
|
|
5
|
+
# LabIMotion template DOI logic for the host's Doi model. The host owns the DOI
|
|
6
|
+
# record and the generic DataCite plumbing (build_suffix/align_suffix, the MDS
|
|
7
|
+
# client, the DataCitePublisher concern); this adds only the LabIMotion-specific
|
|
8
|
+
# class methods that the gem's template DOI usecases and APIs call on ::Doi.
|
|
9
|
+
#
|
|
10
|
+
# The host wires it up with a single line:
|
|
11
|
+
# class Doi < ApplicationRecord
|
|
12
|
+
# include Labimotion::TemplateDoi
|
|
13
|
+
# end
|
|
14
|
+
#
|
|
15
|
+
# Assumes the host `dois` table has a jsonb `metadata` column (the DOI version
|
|
16
|
+
# is stamped there) and that the deterministic suffix survives Doi#align_suffix
|
|
17
|
+
# unchanged (reserve sets inchikey == suffix and version_count: 0 for that).
|
|
18
|
+
module Labimotion
|
|
19
|
+
module TemplateDoi
|
|
20
|
+
extend ActiveSupport::Concern
|
|
21
|
+
|
|
22
|
+
# Literal namespace shared by every LabIMotion template DOI suffix.
|
|
23
|
+
LABIMOTION_DOI_NAMESPACE = 'labimotion'
|
|
24
|
+
|
|
25
|
+
# ActiveSupport::Concern extends this into the including class, so every
|
|
26
|
+
# method below becomes a class method on the host's Doi.
|
|
27
|
+
module ClassMethods
|
|
28
|
+
# Deterministic DOI suffix for a LabIMotion template klass. The same suffix
|
|
29
|
+
# is used at reserve and at release time, so both share one DOI:
|
|
30
|
+
# element -> labimotion/element/<name>/<identifier>/<doi_version>
|
|
31
|
+
# segment -> labimotion/segment/<element>/<identifier>/<doi_version>
|
|
32
|
+
# dataset -> labimotion/dataset/<ols_term_id>/<identifier>/<doi_version>
|
|
33
|
+
# `<identifier>` is the first UUID group (8 hex chars) of the template's
|
|
34
|
+
# identifier/uuid, falling back to the record id. `<doi_version>` is the DOI
|
|
35
|
+
# version (see .labimotion_version_segment). Callers may pass an explicit
|
|
36
|
+
# template version; otherwise the record's current version is used.
|
|
37
|
+
def build_labimotion_suffix(record, version = nil)
|
|
38
|
+
parts = labimotion_suffix_parts(record)
|
|
39
|
+
raise ArgumentError, "unsupported template: #{record.class}" if parts.nil?
|
|
40
|
+
|
|
41
|
+
segment = labimotion_version_segment(record, version)
|
|
42
|
+
return nil if segment.blank?
|
|
43
|
+
|
|
44
|
+
segments = parts.map { |part| sanitize_doi_part(part) }.reject(&:empty?)
|
|
45
|
+
"#{segments.join('/')}/#{segment}"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# The DOI version segment for a template version. A DOI is published per major
|
|
49
|
+
# release: the .0 release opens that version (X.0 -> "X") and later minor
|
|
50
|
+
# revisions roll into the NEXT DOI (X.y, y>=1 -> "X+1"). Sub-1.0 and
|
|
51
|
+
# unversioned/blank templates map to the first DOI (v1).
|
|
52
|
+
# 0.x -> "1" 1.0 -> "1" 1.1..2.0 -> "2" 2.1..3.0 -> "3"
|
|
53
|
+
def labimotion_version_segment(record, version = nil)
|
|
54
|
+
raw = (version.presence || record.try(:version)).to_s.strip
|
|
55
|
+
parts = raw.split('.')
|
|
56
|
+
major = parts[0].to_i
|
|
57
|
+
minor = parts[1].to_i
|
|
58
|
+
return '1' if major.zero?
|
|
59
|
+
return major.to_s if minor.zero?
|
|
60
|
+
|
|
61
|
+
(major + 1).to_s
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# The DOIs reserved for a LabIMotion template, in reservation order.
|
|
65
|
+
def labimotion_dois(record)
|
|
66
|
+
where(doiable_id: record.id, doiable_type: record.class.name).order(:id).to_a
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# The current (most recently reserved) DOI for a template, or nil.
|
|
70
|
+
def labimotion_latest_doi(record)
|
|
71
|
+
labimotion_dois(record).last
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# The DOI version (next-major integer) recorded on a reserved template DOI.
|
|
75
|
+
def labimotion_doi_version(doi)
|
|
76
|
+
doi.metadata.to_h.dig('labimotion', 'doi_version')
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Metadata stamped on a reserved template DOI so the version it represents
|
|
80
|
+
# survives on the record (used to gate reserving the next version).
|
|
81
|
+
def labimotion_doi_metadata(record, version = nil)
|
|
82
|
+
{ 'labimotion' => { 'doi_version' => labimotion_version_segment(record, version) } }
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def labimotion_suffix_parts(record)
|
|
86
|
+
# identifier/uuid may both be blank for a draft, which would collapse the
|
|
87
|
+
# scope (colliding across templates). Fall back to the stable record id so
|
|
88
|
+
# every template gets a unique, deterministic suffix. Resolved lazily so an
|
|
89
|
+
# unsupported record (no #id) still falls through to the ArgumentError in the
|
|
90
|
+
# caller. The identifier is shortened to its first UUID group (8 hex chars).
|
|
91
|
+
# A segment's <element> is the name of the ElementKlass it belongs to.
|
|
92
|
+
identifier = lambda do
|
|
93
|
+
raw = record.try(:identifier).presence || record.try(:uuid).presence || record.id
|
|
94
|
+
raw.to_s.split('-').first
|
|
95
|
+
end
|
|
96
|
+
case record
|
|
97
|
+
when ::Labimotion::ElementKlass
|
|
98
|
+
[LABIMOTION_DOI_NAMESPACE, 'element', record.name, identifier.call]
|
|
99
|
+
when ::Labimotion::SegmentKlass
|
|
100
|
+
[LABIMOTION_DOI_NAMESPACE, 'segment', record.element_klass&.name, identifier.call]
|
|
101
|
+
when ::Labimotion::DatasetKlass
|
|
102
|
+
[LABIMOTION_DOI_NAMESPACE, 'dataset', record.ols_term_id, identifier.call]
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Keeps a suffix segment DOI-safe: trims, collapses whitespace to hyphens and
|
|
107
|
+
# drops anything outside [A-Za-z0-9._-] (colons stripped, as elsewhere here).
|
|
108
|
+
def sanitize_doi_part(value)
|
|
109
|
+
value.to_s.strip.gsub(/\s+/, '-').gsub(/[^A-Za-z0-9._-]/, '')
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
@@ -11,7 +11,11 @@ module Labimotion
|
|
|
11
11
|
class BuildTemplateDoiXml
|
|
12
12
|
include ::DataCitePublisher
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
# The template ships with the gem. A host app may still override it by
|
|
15
|
+
# placing its own copy at HOST_TEMPLATE_PATH, which is how it used to be
|
|
16
|
+
# sourced — hence the lookup order below.
|
|
17
|
+
GEM_TEMPLATE_PATH = File.expand_path('../libs/data/datacite/labimotion_template.html.erb', __dir__)
|
|
18
|
+
HOST_TEMPLATE_PATH = 'app/publish/datacite_metadata_labimotion_template.html.erb'
|
|
15
19
|
|
|
16
20
|
RESOURCE_LABEL = {
|
|
17
21
|
'element' => 'LabIMotion Element Template',
|
|
@@ -29,11 +33,19 @@ module Labimotion
|
|
|
29
33
|
def call
|
|
30
34
|
return nil if @doi.nil?
|
|
31
35
|
|
|
32
|
-
ERB.new(File.read(
|
|
36
|
+
ERB.new(File.read(template_path), trim_mode: '-').result(binding)
|
|
33
37
|
end
|
|
34
38
|
|
|
35
39
|
private
|
|
36
40
|
|
|
41
|
+
# Resolved per call rather than at load time, so the class no longer needs
|
|
42
|
+
# Rails to be booted just to be autoloaded.
|
|
43
|
+
def template_path
|
|
44
|
+
# `Rails.root` is still nil if Rails is loaded but the app has not booted.
|
|
45
|
+
host = defined?(Rails) && Rails.respond_to?(:root) ? Rails.root&.join(HOST_TEMPLATE_PATH) : nil
|
|
46
|
+
host && File.exist?(host) ? host : GEM_TEMPLATE_PATH
|
|
47
|
+
end
|
|
48
|
+
|
|
37
49
|
def full_doi
|
|
38
50
|
@doi.full_doi
|
|
39
51
|
end
|
data/lib/labimotion/version.rb
CHANGED
data/lib/labimotion.rb
CHANGED
|
@@ -148,4 +148,5 @@ module Labimotion
|
|
|
148
148
|
autoload :Datasetable, 'labimotion/models/concerns/datasetable'
|
|
149
149
|
autoload :AttachmentConverter, 'labimotion/models/concerns/attachment_converter'
|
|
150
150
|
autoload :LinkedProperties, 'labimotion/models/concerns/linked_properties'
|
|
151
|
+
autoload :TemplateDoi, 'labimotion/models/concerns/template_doi'
|
|
151
152
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: labimotion
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.2.0.
|
|
4
|
+
version: 2.2.0.rc19
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Chia-Lin Lin
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2026-07-
|
|
12
|
+
date: 2026-07-27 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: caxlsx
|
|
@@ -111,6 +111,7 @@ files:
|
|
|
111
111
|
- lib/labimotion/helpers/vocabulary_helpers.rb
|
|
112
112
|
- lib/labimotion/libs/attachment_handler.rb
|
|
113
113
|
- lib/labimotion/libs/converter.rb
|
|
114
|
+
- lib/labimotion/libs/data/datacite/labimotion_template.html.erb
|
|
114
115
|
- lib/labimotion/libs/data/mapper/Chemwiki.json
|
|
115
116
|
- lib/labimotion/libs/data/mapper/Source.json
|
|
116
117
|
- lib/labimotion/libs/data/vocab/Standard.json
|
|
@@ -136,6 +137,7 @@ files:
|
|
|
136
137
|
- lib/labimotion/models/concerns/linked_properties.rb
|
|
137
138
|
- lib/labimotion/models/concerns/metadata_validation.rb
|
|
138
139
|
- lib/labimotion/models/concerns/segmentable.rb
|
|
140
|
+
- lib/labimotion/models/concerns/template_doi.rb
|
|
139
141
|
- lib/labimotion/models/concerns/workflow.rb
|
|
140
142
|
- lib/labimotion/models/dataset.rb
|
|
141
143
|
- lib/labimotion/models/dataset_klass.rb
|