Class: String

Inherits:
Object
  • Object
show all
Defined in:
lib/ndr_support/string/cleaning.rb,
lib/ndr_support/string/conversions.rb

Constant Summary collapse

INVALID_CONTROL_CHARS =
/[\x00-\x08\x0b-\x0c\x0e-\x1f]/
ROMAN_ONE_TO_FIVE_MAPPING =
{ 'I' => '1', 'II' => '2', 'III' => '3', 'IIII' => '4', 'IV' => '4', 'V' => '5' }
POSTCODE_REGEXP =
/
  ^(
    [A-Z][0-9]           |
    [A-Z][0-9][0-9]      |
    [A-Z][0-9][A-Z]      |
    [A-Z][A-Z][0-9]      |
    NPT                  |
    [A-Z][A-Z][0-9][0-9] |
    [A-Z][A-Z][0-9][A-Z]
  )
  [0-9][A-Z][A-Z]
$/x
SOUNDEX_CHARS =
'BPFVCSKGJQXZDTLMNR'
SOUNDEX_NUMS =
'111122222222334556'
SOUNDEX_CHARS_EX =
'^' + SOUNDEX_CHARS
SOUNDEX_CHARS_DEL =
'^A-Z'

Instance Method Summary collapse

Instance Method Details

#clean(what) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/ndr_support/string/cleaning.rb', line 46

def clean(what)
  case what
  when :nhsnumber
    delete('^0-9')[0..9]
  when :postcode, :get_postcode
    postcodeize(:db)
  when :lpi
    upcase.delete('^0-9A-Z')
  when :gender
    if self =~ /\AM(ale)?/i
      '1'
    elsif self =~ /\AF(emale)?/i
      '2'
    else
      self
    end
  when :sex
    # SECURE: BNS 2012-10-09: But may behave oddly for multi-line input
    if self =~ /^M|1/i
      '1'
    elsif self =~ /^F|2/i
      '2'
    else
      '0'
    end
  when :sex_c
    if self =~ /^M|1/i
      'M'
    elsif self =~ /^F|2/i
      'F'
    else
      ''
    end
  when :name
    substitutions = {
      '.'      => '',
      /,|;/    => ' ',
      /\s{2,}/ => ' ',
      '`'      => '\''
    }
    substitutions.inject(upcase) { |a, e| a.gsub(*e) }.strip
  when :ethniccategory
    replace_ethniccategory = {
      '0' => '0',
      '1' => 'M',
      '2' => 'N',
      '3' => 'H',
      '4' => 'J',
      '5' => 'K',
      '6' => 'R',
      '7' => '8',
      '&' => 'X',
      ' ' => 'X',
      '99' => 'X'
    }
    replace_ethniccategory[self] || upcase
  when :code
    split_on_separators.map do |code|
      code.blank? ? next : code.delete('.')
    end.compact.join(' ')
  when :code_icd
    warn '[DEPRECATION] clean(:code_icd) is deprecated - consider using clean(:icd) instead.'
    # regexp = /[A-Z][0-9]{2}(\.(X|[0-9]{1,2})|[0-9]?)( *(D|A)( |,|;|$))/
    codes = upcase.split_on_separators.delete_if { |x| x.squash.blank? }
    cleaned_codes = []
    codes.each do |code|
      if code == 'D' || code == 'A'
        cleaned_codes[-1] += code
      else
        cleaned_codes << code
      end
    end
    cleaned_codes.join(' ')
  when :icd
    codes = upcase.squish.split_on_separators.reject(&:blank?)
    codes.map { |code| code.gsub(/(?<=\d)(\.?X?)/, '') }.join(' ')
  when :code_opcs
    clean_code_opcs
  when :hospitalnumber
    self[-1..-1] =~ /\d/ ? self : self[0..-2]
  when :xmlsafe, :make_xml_safe
    strip_xml_unsafe_characters
  when :roman5
    # This deromanises roman numerals between 1 and 5
    gsub(/[IV]+/i) { |match| ROMAN_ONE_TO_FIVE_MAPPING[match.upcase] }
  when :tnmcategory
    sub!(/\A[tnm]/i, '')
    if self =~ /\Ax\z/i
      upcase
    else
      downcase
    end
  when :strip, :upcase, :itself
    # SECURE: 14-06-2017 TPG Fixed list of executable methods (whats)
    send(what)
  else
    gsub(' ?', ' ')
  end
end

#date1Object



40
41
42
# File 'lib/ndr_support/string/conversions.rb', line 40

def date1
  Daterange.new(self).date1
end

#date2Object



44
45
46
# File 'lib/ndr_support/string/conversions.rb', line 44

def date2
  Daterange.new(self).date2
end

#nhs_numberizeObject

Show NHS numbers with spaces



74
75
76
77
# File 'lib/ndr_support/string/conversions.rb', line 74

def nhs_numberize
  return self unless length == 10
  self[0..2] + ' ' + self[3..5] + ' ' + self[6..9]
end

#orig_to_datetimeObject



128
# File 'lib/ndr_support/string/conversions.rb', line 128

alias orig_to_datetime to_datetime

#postcodeize(option = :user) ⇒ Object

Show postcode in various formats. Parameter “option” can be :user, :compact, :db



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/ndr_support/string/cleaning.rb', line 27

def postcodeize(option = :user)
  nspce = gsub(/[[:space:]]/, '').upcase
  unless nspce.blank? || POSTCODE_REGEXP =~ nspce
    return self # Don't change old-style or malformed postcodes
  end
  case option
  when :compact
    nspce
  when :db
    case nspce.length
    when 5 then nspce.insert(-4, '  ')
    when 6 then nspce.insert(-4, ' ')
    else nspce
    end
  else # anything else, including :user --> friendly format
    nspce.length < 5 ? nspce : nspce.insert(-4, ' ')
  end
end

#soundex(census = true) ⇒ Object



26
27
28
29
30
31
32
33
34
# File 'lib/ndr_support/string/conversions.rb', line 26

def soundex(census = true)
  str = upcase.delete(SOUNDEX_CHARS_DEL).squeeze

  str[0..0] + str[1..-1].
    delete(SOUNDEX_CHARS_EX).
    tr(SOUNDEX_CHARS, SOUNDEX_NUMS)[0..(census ? 2 : -1)].
    squeeze[0..(census ? 2 : -1)].
    ljust(3, '0') rescue ''
end

#sounds_like(other) ⇒ Object



36
37
38
# File 'lib/ndr_support/string/conversions.rb', line 36

def sounds_like(other)
  soundex == other.soundex
end

#squashObject

Used for comparing addresses



21
22
23
# File 'lib/ndr_support/string/cleaning.rb', line 21

def squash
  upcase.delete('^A-Z0-9')
end

#strip_xml_unsafe_charactersObject



146
147
148
# File 'lib/ndr_support/string/cleaning.rb', line 146

def strip_xml_unsafe_characters
  gsub(String::INVALID_CONTROL_CHARS, '')
end

#surname_and_initialsObject

Convert “SMITH JD” into “Smith JD”



57
58
59
60
61
# File 'lib/ndr_support/string/conversions.rb', line 57

def surname_and_initials
  a = split
  initials = a.pop
  a.collect(&:capitalize).join(' ') + ' ' + initials
end

#surnameizeObject

Like titleize but copes with Scottish and Irish names.



64
65
66
67
68
69
70
71
# File 'lib/ndr_support/string/conversions.rb', line 64

def surnameize
  s = slice(0, 2).upcase
  if s == 'MC' || s == "O'"
    s.titleize + slice(2..-1).titleize
  else
    titleize
  end
end

#thedateObject



48
49
50
# File 'lib/ndr_support/string/conversions.rb', line 48

def thedate
  Ourdate.new(self).thedate
end

#thetimeObject



52
53
54
# File 'lib/ndr_support/string/conversions.rb', line 52

def thetime
  Ourtime.new(self).thetime
end

#to_booleanObject

Try to convert the string value into boolean



143
144
145
146
147
148
# File 'lib/ndr_support/string/conversions.rb', line 143

def to_boolean
  # SECURE: BNS 2012-10-09: But may behave oddly for multi-line input
  return true if self == true || self =~ (/^(true|t|yes|y|1)$/i)
  return false if self == false || self.nil? || self =~ (/^(false|f|no|n|0)$/i)
  fail ArgumentError, "invalid value for Boolean: \"#{self}\""
end

#to_datetimeObject



130
131
132
133
134
135
136
137
138
139
140
# File 'lib/ndr_support/string/conversions.rb', line 130

def to_datetime
  # Default timezone for to_datetime conversion is GMT, not local timezone
  default_timezone = if ActiveRecord.respond_to?(:default_timezone)
                       ActiveRecord.default_timezone
                     else
                       ActiveRecord::Base.default_timezone # Rails <= 6.1
                     end
  return to_time.to_datetime if default_timezone == :local

  orig_to_datetime
end

#truncate_hellip(n) ⇒ Object

truncate a string, with a HTML &hellip; at the end



80
81
82
# File 'lib/ndr_support/string/conversions.rb', line 80

def truncate_hellip(n)
  length > n ? slice(0, n - 1) + '&hellip;' : self
end

#xml_unsafe?Boolean

Returns:

  • (Boolean)


150
151
152
# File 'lib/ndr_support/string/cleaning.rb', line 150

def xml_unsafe?
  self =~ String::INVALID_CONTROL_CHARS
end