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.



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

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



48
49
50
51
52
53
54
55
56
57
58
# File 'lib/pubid/identifier.rb', line 48

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)


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

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

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

#exclude(*args) ⇒ Object



157
158
159
160
161
162
163
164
165
166
# File 'lib/pubid/identifier.rb', line 157

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



196
197
198
# File 'lib/pubid/identifier.rb', line 196

def hash
  @hash ||= compute_hash
end

#mr_numberObject



119
120
121
# File 'lib/pubid/identifier.rb', line 119

def mr_number
  number&.to_s
end

#mr_number_with_partObject



111
112
113
114
115
116
117
# File 'lib/pubid/identifier.rb', line 111

def mr_number_with_part
  num = mr_number
  return nil unless num

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

#mr_partObject



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

def mr_part
  part&.to_s
end

#mr_publisherObject

MR string template methods — flavors override as needed



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

def mr_publisher
  publisher&.to_s
end

#mr_typeObject



102
103
104
105
106
107
108
109
# File 'lib/pubid/identifier.rb', line 102

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



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

def mr_year
  date&.year&.to_s
end

#new_edition_of?(other) ⇒ Boolean

Returns:

  • (Boolean)


168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/pubid/identifier.rb', line 168

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



74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/pubid/identifier.rb', line 74

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



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

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

#rootObject



67
68
69
70
71
# File 'lib/pubid/identifier.rb', line 67

def root
  return base_identifier.root if base_identifier

  self
end

#to_mr_stringObject



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

def to_mr_string
  render(format: :mr_string)
end

#to_s(**opts) ⇒ Object



89
90
91
# File 'lib/pubid/identifier.rb', line 89

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

#to_supplement_s(**opts) ⇒ Object

Supplement rendering hook — flavors override for supplement-specific rendering



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

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

#to_urnObject

Default URN generation — resolves flavor’s UrnGenerator class



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

def to_urn
  resolve_urn_generator.new(self).generate
end

#urn_supplement_typeObject



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

def urn_supplement_type
  nil
end

#urn_type_codeObject

URN template methods — flavors override as needed



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

def urn_type_code
  nil
end