Class: Pubid::Identifier

Inherits:
Lutaml::Model::Serializable
  • Object
show all
Defined in:
lib/pubid/identifier.rb

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attrs = {}, options = {}) ⇒ Identifier

Returns a new instance of Identifier.



47
48
49
50
51
# File 'lib/pubid/identifier.rb', line 47

def initialize(attrs = {}, options = {})
  attrs = attrs.dup
  attrs[:_type] ||= self.class.polymorphic_name
  super
end

Class Attribute Details

.format_registryObject



15
16
17
# File 'lib/pubid/identifier.rb', line 15

def format_registry
  @format_registry || superclass&.format_registry
end

Class Method Details

.polymorphic_nameObject



53
54
55
56
57
58
59
60
61
62
63
# File 'lib/pubid/identifier.rb', line 53

def self.polymorphic_name
  return nil unless name

  parts = name.split("::")
  flavor = parts[1]&.downcase
  type_kebab = parts.last
    .gsub(/([A-Z]+)([A-Z][a-z])/, '\1-\2')
    .gsub(/([a-z\d])([A-Z])/, '\1-\2')
    .downcase
  "pubid:#{flavor}:#{type_kebab}"
end

Instance Method Details

#base_identifierObject

base_identifier is declared by supplement subclasses with proper type



38
39
40
# File 'lib/pubid/identifier.rb', line 38

def base_identifier
  nil
end

#eql?(other) ⇒ Boolean

Returns:

  • (Boolean)


205
206
207
208
209
# File 'lib/pubid/identifier.rb', line 205

def eql?(other)
  return false unless other.is_a?(self.class)

  hash == other.hash && self == other
end

#exclude(*args) ⇒ Object



162
163
164
165
166
167
168
169
170
171
# File 'lib/pubid/identifier.rb', line 162

def exclude(*args)
  excluded_args = args.dup
  # Map :year to :date since identifiers store years inside date
  excluded_args << :date if excluded_args.delete(:year)

  attrs = self.class.attributes.each_with_object({}) do |(name, _), h|
    h[name] = excluded_args.include?(name) ? nil : send(name)
  end
  self.class.new(attrs)
end

#hashObject



201
202
203
# File 'lib/pubid/identifier.rb', line 201

def hash
  @hash ||= compute_hash
end

#mr_numberObject



124
125
126
# File 'lib/pubid/identifier.rb', line 124

def mr_number
  number&.to_s
end

#mr_number_with_partObject



116
117
118
119
120
121
122
# File 'lib/pubid/identifier.rb', line 116

def mr_number_with_part
  num = mr_number
  return nil unless num

  prt = mr_part
  prt ? "#{num}-#{prt}" : num
end

#mr_partObject



128
129
130
# File 'lib/pubid/identifier.rb', line 128

def mr_part
  part&.to_s
end

#mr_publisherObject

MR string template methods — flavors override as needed



103
104
105
# File 'lib/pubid/identifier.rb', line 103

def mr_publisher
  publisher&.to_s
end

#mr_typeObject



107
108
109
110
111
112
113
114
# File 'lib/pubid/identifier.rb', line 107

def mr_type
  return nil unless typed_stage

  code = typed_stage.type_code
  return nil if code.nil? || code.empty? || code == "is"

  code
end

#mr_yearObject



132
133
134
# File 'lib/pubid/identifier.rb', line 132

def mr_year
  date&.year&.to_s
end

#new_edition_of?(other) ⇒ Boolean

Returns:

  • (Boolean)


173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/pubid/identifier.rb', line 173

def new_edition_of?(other)
  unless publisher == other.publisher
    raise ArgumentError,
          "Cannot compare edition: different publisher"
  end
  unless number == other.number
    raise ArgumentError,
          "Cannot compare edition: different number"
  end
  unless part == other.part
    raise ArgumentError,
          "Cannot compare edition: different part"
  end

  unless date && other.date
    raise ArgumentError,
          "Cannot compare identifier without date/year"
  end

  return date.year > other.date.year if date.year != other.date.year

  if edition && other.edition
    return edition.number > other.edition.number
  end

  false
end

#render(format: :human, **opts) ⇒ Object

Unified render — delegates to format registry



79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/pubid/identifier.rb', line 79

def render(format: :human, **opts)
  registry = self.class.format_registry
  unless registry
    raise ArgumentError, "No format registry configured on #{self.class}"
  end

  renderer = registry.renderer_for(format)
  unless renderer
    raise ArgumentError, "No renderer registered for format: #{format}"
  end

  context = build_rendering_context(renderer, format:, **opts)
  renderer.new(self).render(context:, **opts.slice(:with_edition))
end

#resolve_urn_generatorObject



155
156
157
158
159
160
# File 'lib/pubid/identifier.rb', line 155

def resolve_urn_generator
  flavor = self.class.name.split("::")[1]
  Object.const_get("Pubid::#{flavor}::UrnGenerator")
rescue NameError
  Pubid::UrnGenerator::Base
end

#rootObject



72
73
74
75
76
# File 'lib/pubid/identifier.rb', line 72

def root
  return base_identifier.root if base_identifier

  self
end

#to_mr_stringObject



98
99
100
# File 'lib/pubid/identifier.rb', line 98

def to_mr_string
  render(format: :mr_string)
end

#to_s(**opts) ⇒ Object



94
95
96
# File 'lib/pubid/identifier.rb', line 94

def to_s(**opts)
  render(format: :human, **opts)
end

#to_supplement_s(**opts) ⇒ Object

Supplement rendering hook — flavors override for supplement-specific rendering



146
147
148
# File 'lib/pubid/identifier.rb', line 146

def to_supplement_s(**opts)
  to_s(**opts)
end

#to_urnObject

Default URN generation — resolves flavor’s UrnGenerator class



151
152
153
# File 'lib/pubid/identifier.rb', line 151

def to_urn
  resolve_urn_generator.new(self).generate
end

#urn_supplement_typeObject



141
142
143
# File 'lib/pubid/identifier.rb', line 141

def urn_supplement_type
  nil
end

#urn_type_codeObject

URN template methods — flavors override as needed



137
138
139
# File 'lib/pubid/identifier.rb', line 137

def urn_type_code
  nil
end

#yearString?

Returns publication year from the date component.

Returns:

  • (String, nil)

    publication year from the date component



43
44
45
# File 'lib/pubid/identifier.rb', line 43

def year
  date&.year&.to_s
end