Class: Pubid::Nist::Identifiers::Base

Inherits:
Identifier
  • Object
show all
Defined in:
lib/pubid/nist/identifiers/base.rb

Overview

Base NIST/NBS identifier class Each series type inherits from this and overrides series_code

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Identifier

#base_identifier, #eql?, #exclude, #hash, #mr_number, #mr_number_with_part, #mr_part, #mr_publisher, #mr_type, #mr_year, #new_edition_of?, polymorphic_name, #render, #resolve_urn_generator, #root, #to_mr_string, #to_supplement_s, #to_urn, #urn_supplement_type, #urn_type_code

Constructor Details

#initialize(**attributes) ⇒ Base

Returns a new instance of Base.



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/pubid/nist/identifiers/base.rb', line 71

def initialize(**attributes)
  super()

  attrs = self.class.attributes
  attributes.each do |key, value|
    next if value.nil?

    setter = :"#{key}="
    public_send(setter, value) if attrs.key?(key)
  end

  # NOTE: Compound number building is handled by the Builder class
  # Do NOT build compound numbers here - let the builder apply special patterns first
  # See lib/pubid/nist/builder.rb lines 368-472 for compound number logic
end

Class Method Details

.typed_stagesObject

Default: no typed stages. Subclasses override as needed.



10
11
12
# File 'lib/pubid/nist/identifiers/base.rb', line 10

def self.typed_stages
  []
end

Instance Method Details

#edition_greater?(edition1, edition2) ⇒ Boolean

Helper to compare edition values numerically

Returns:

  • (Boolean)

    true if edition1 is greater than edition2



185
186
187
188
189
# File 'lib/pubid/nist/identifiers/base.rb', line 185

def edition_greater?(edition1, edition2)
  num1 = extract_edition_number(edition1)
  num2 = extract_edition_number(edition2)
  num1 && num2 && num1 > num2
end

#extract_edition_number(edition) ⇒ Integer?

Extract numeric value from edition (r3 -> 3, r5 -> 5, e2 -> 2)

Returns:

  • (Integer, nil)

    the edition number or nil if not extractable



193
194
195
196
197
198
199
# File 'lib/pubid/nist/identifiers/base.rb', line 193

def extract_edition_number(edition)
  # Handle both String and Edition component
  edition_str = edition.to_s
  # Match patterns like r3, r5, e2, etc.
  match = edition_str.match(/^[er]?(\d+)$/)
  match ? match[1].to_i : nil
end

#languageObject

Backward compatibility: language method returns translation_component This allows tests to use parsed.language instead of parsed.translation_component



106
107
108
# File 'lib/pubid/nist/identifiers/base.rb', line 106

def language
  translation_component
end

#merge(document) ⇒ Base

Merge another document into this one Used for combining document data, preferring more specific values

Parameters:

  • document (Base)

    another NIST document to merge

Returns:

  • (Base)

    self with merged attributes



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/pubid/nist/identifiers/base.rb', line 149

def merge(document)
  return self unless document.is_a?(Base)

  attrs = self.class.attributes
  attrs.each_key do |var_name|
    next if var_name == :rendering_style
    next if var_name == :parsed_format

    current_val = public_send(var_name)
    new_val = document.public_send(var_name)
    next unless new_val

    should_merge = case var_name
                   when :publisher, :series, :number
                     true
                   when :edition
                     current_val.nil? || edition_greater?(new_val,
                                                          current_val)
                   when :volume, :part, :version, :revision
                     current_val.nil? || (new_val.to_s.length > current_val.to_s.length)
                   when :supplement, :errata, :index, :insert, :section, :appendix, :translation
                     true
                   when :year, :month, :update, :draft
                     true
                   else
                     false
                   end

    public_send(:"#{var_name}=", new_val) if should_merge
  end

  self
end

#publisherString

Generate URN for this identifier

Returns:

  • (String)

    URN representation



18
# File 'lib/pubid/nist/identifiers/base.rb', line 18

attribute :publisher, Components::Publisher

#revisionString?

Compute revision from edition component for backward compatibility

Returns:

  • (String, nil)

    revision string (e.g., “r5”) or nil



89
90
91
92
93
94
95
96
# File 'lib/pubid/nist/identifiers/base.rb', line 89

def revision
  return @revision if @revision

  # Compute from edition component if available
  if edition&.type && edition.id
    "#{edition.type}#{edition.id}"
  end
end

#series_codeObject

Default series_code — subclasses override to provide a normalized series name.



67
68
69
# File 'lib/pubid/nist/identifiers/base.rb', line 67

def series_code
  nil
end

#to_s(format = nil) ⇒ Object

Generate identifier string in specified format

Parameters:

  • format (:full, :long, :abbreviated, :short, :mr) (defaults to: nil)

    output format



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/pubid/nist/identifiers/base.rb', line 112

def to_s(format = nil)
  # Handle both keyword argument (hash) and positional argument (symbol/string)
  format = format[:format] if format.is_a?(Hash)

  # Default to parsed_format if available (preserves input format on round-trip)
  # Falls back to :short format for output (normalization)
  # Explicit format parameter always overrides parsed_format
  effective_format = format || parsed_format&.to_sym || :short
  effective_format = effective_format.to_sym if effective_format.is_a?(String)
  case effective_format
  when :full, :long
    to_full_style
  when :abbreviated, :abbrev
    to_abbreviated_style
  when :short
    to_short_style
  when :mr
    to_mr_style
  else
    to_short_style
  end
end

#translationObject

Backward compatibility: translation method returns translation_component This allows tests to use parsed.translation.language instead of parsed.translation_component.language



100
101
102
# File 'lib/pubid/nist/identifiers/base.rb', line 100

def translation
  translation_component
end

#weightInteger

Returns weight based on amount of defined attributes Used for ranking identifiers by specificity for conflict resolution

Returns:

  • (Integer)

    weight score (higher = more specific)



138
139
140
141
142
143
# File 'lib/pubid/nist/identifiers/base.rb', line 138

def weight
  self.class.attributes.keys.inject(0) do |sum, key|
    val = public_send(key)
    val && !val.to_s.empty? ? sum + 1 : sum
  end
end