Class: SecID::Base

Inherits:
Object
  • Object
show all
Includes:
Generatable, Normalizable, Validatable
Defined in:
lib/sec_id/base.rb

Overview

Base class for securities identifiers that provides a common interface for validation, normalization, and parsing.

Subclasses must implement:

  • ID_REGEX constant with named capture groups for parsing
  • initialize method that calls parse and extracts components

Subclasses with check digits should also include the Checkable concern, which provides check-digit validation, calculation, and restoration.

Examples:

Implementing a check-digit identifier

class MyIdentifier < Base
  include Checkable

  ID_REGEX = /\A(?<identifier>[A-Z]{6})(?<check_digit>\d)?\z/x

  def initialize(id)
    parts = parse(id)
    @identifier = parts[:identifier]
    @check_digit = parts[:check_digit]&.to_i
  end

  def calculate_check_digit
    validate_format_for_calculation!
    mod10(some_algorithm)
  end
end

Implementing a non-check-digit identifier

class SimpleId < Base
  ID_REGEX = /\A(?<identifier>[A-Z]{6})\z/x

  def initialize(id)
    parts = parse(id)
    @identifier = parts[:identifier]
  end
end

Direct Known Subclasses

BIC, CEI, CFI, CIK, CUSIP, DTI, FIGI, FISN, IBAN, ISIN, LEI, OCC, SEDOL, Valoren, WKN

Constant Summary

Constants included from Generatable

Generatable::ALPHA, Generatable::ALPHANUMERIC, Generatable::DIGITS

Constants included from Validatable

Validatable::ERROR_MAP

Constants included from Normalizable

Normalizable::SEPARATORS

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Validatable

#errors, #valid?, #validate, #validate!

Methods included from Normalizable

#normalize!, #normalized, #to_pretty_s, #to_s, #to_str

Constructor Details

#initialize(_sec_id_number) ⇒ Base

Subclasses must override this method.

Parameters:

  • _sec_id_number (String)

    the identifier string to parse

Raises:

  • (NotImplementedError)

    always raised in base class



95
96
97
# File 'lib/sec_id/base.rb', line 95

def initialize(_sec_id_number)
  raise NotImplementedError
end

Instance Attribute Details

#full_idString (readonly)

Returns the original input after normalization (stripped and uppercased).

Returns:

  • (String)

    the original input after normalization (stripped and uppercased)



47
48
49
# File 'lib/sec_id/base.rb', line 47

def full_id
  @full_id
end

#identifierString? (readonly)

Returns the main identifier portion (without check digit).

Returns:

  • (String, nil)

    the main identifier portion (without check digit)



50
51
52
# File 'lib/sec_id/base.rb', line 50

def identifier
  @identifier
end

Class Method Details

.exampleString

Returns a representative valid identifier string.

Returns:

  • (String)

    a representative valid identifier string



74
# File 'lib/sec_id/base.rb', line 74

def example = self::EXAMPLE

.full_nameString

Returns the full human-readable standard name.

Returns:

  • (String)

    the full human-readable standard name



57
# File 'lib/sec_id/base.rb', line 57

def full_name = self::FULL_NAME

.has_check_digit?Boolean

Returns true if this identifier type uses a check digit.

Returns:

  • (Boolean)

    true if this identifier type uses a check digit



77
78
79
80
81
# File 'lib/sec_id/base.rb', line 77

def has_check_digit?
  return @has_check_digit if defined?(@has_check_digit)

  @has_check_digit = ancestors.include?(SecID::Checkable)
end

.id_lengthInteger, ...

Returns the fixed length, valid length range, or discrete valid lengths.

Returns:

  • (Integer, Range, Array<Integer>)

    the fixed length, valid length range, or discrete valid lengths



60
# File 'lib/sec_id/base.rb', line 60

def id_length = self::ID_LENGTH

.length_specificityInteger

Specificity weight from ID_LENGTH: fewer valid lengths ranks more specific.

Returns:

  • (Integer)


71
# File 'lib/sec_id/base.rb', line 71

def length_specificity = (v = self::ID_LENGTH).is_a?(Integer) ? 1 : v.size

.length_valuesArray<Integer>, Range

Valid length values, for length-table indexing. Integer wraps to a one-element Array; Range and Array both yield their own elements.

Returns:

  • (Array<Integer>, Range)


66
# File 'lib/sec_id/base.rb', line 66

def length_values = (v = self::ID_LENGTH).is_a?(Integer) ? [v] : v

.short_nameString

Returns the unqualified class name (e.g. "ISIN", "CUSIP").

Returns:

  • (String)

    the unqualified class name (e.g. "ISIN", "CUSIP")



54
# File 'lib/sec_id/base.rb', line 54

def short_name = @short_name ||= name.split('::').last

Instance Method Details

#==(other) ⇒ Boolean Also known as: eql?

Parameters:

  • other (Object)

Returns:

  • (Boolean)


101
102
103
# File 'lib/sec_id/base.rb', line 101

def ==(other)
  other.class == self.class && comparison_id == other.comparison_id
end

#as_jsonHash

Returns a JSON-compatible hash representation.

Returns:

  • (Hash)


128
129
130
# File 'lib/sec_id/base.rb', line 128

def as_json(*)
  to_h
end

#hashInteger

Returns:

  • (Integer)


108
109
110
# File 'lib/sec_id/base.rb', line 108

def hash
  [self.class, comparison_id].hash
end

#to_hHash

Returns a hash representation of this identifier for serialization.

Returns:

  • (Hash)

    hash with :type, :full_id, :normalized, :valid, and :components keys



115
116
117
118
119
120
121
122
123
# File 'lib/sec_id/base.rb', line 115

def to_h
  {
    type: self.class.short_name.downcase.to_sym,
    full_id: full_id,
    normalized: valid? ? normalized : nil,
    valid: valid?,
    components: components
  }
end