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.



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

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

Class Attribute Details

.format_registryObject



6
7
8
# File 'lib/pubid/identifier.rb', line 6

def format_registry
  @format_registry || superclass&.format_registry
end

Class Method Details

.polymorphic_nameObject



44
45
46
47
48
49
50
51
52
53
54
# File 'lib/pubid/identifier.rb', line 44

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



29
30
31
# File 'lib/pubid/identifier.rb', line 29

def base_identifier
  nil
end

#eql?(other) ⇒ Boolean

Returns:

  • (Boolean)


190
191
192
193
194
# File 'lib/pubid/identifier.rb', line 190

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

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

#exclude(*args) ⇒ Object



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

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 : public_send(name)
  end
  self.class.new(attrs)
end

#hashObject



186
187
188
# File 'lib/pubid/identifier.rb', line 186

def hash
  @hash ||= compute_hash
end

#mr_numberObject



109
110
111
# File 'lib/pubid/identifier.rb', line 109

def mr_number
  number&.to_s
end

#mr_number_with_partObject



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

def mr_number_with_part
  num = mr_number
  return nil unless num

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

#mr_partObject



113
114
115
# File 'lib/pubid/identifier.rb', line 113

def mr_part
  part&.to_s
end

#mr_publisherObject

MR string template methods — flavors override as needed



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

def mr_publisher
  publisher&.to_s
end

#mr_typeObject



92
93
94
95
96
97
98
99
# File 'lib/pubid/identifier.rb', line 92

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



117
118
119
# File 'lib/pubid/identifier.rb', line 117

def mr_year
  date&.year&.to_s
end

#new_edition_of?(other) ⇒ Boolean

Returns:

  • (Boolean)


158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/pubid/identifier.rb', line 158

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



64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/pubid/identifier.rb', line 64

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



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

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

#rootObject



57
58
59
60
61
# File 'lib/pubid/identifier.rb', line 57

def root
  return base_identifier.root if base_identifier

  self
end

#to_mr_stringObject



83
84
85
# File 'lib/pubid/identifier.rb', line 83

def to_mr_string
  render(format: :mr_string)
end

#to_s(**opts) ⇒ Object



79
80
81
# File 'lib/pubid/identifier.rb', line 79

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

#to_supplement_s(**opts) ⇒ Object

Supplement rendering hook — flavors override for supplement-specific rendering



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

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

#to_urnObject

Default URN generation — resolves flavor’s UrnGenerator class



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

def to_urn
  resolve_urn_generator.new(self).generate
end

#urn_supplement_typeObject



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

def urn_supplement_type
  nil
end

#urn_type_codeObject

URN template methods — flavors override as needed



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

def urn_type_code
  nil
end

#yearString?

Returns publication year from the date component.

Returns:

  • (String, nil)

    publication year from the date component



34
35
36
# File 'lib/pubid/identifier.rb', line 34

def year
  date&.year&.to_s
end